From bcdd514a633e27c29d5c00355311f6432cf31e8a Mon Sep 17 00:00:00 2001 From: Yu Zeng Date: Thu, 7 Nov 2024 20:55:40 +0800 Subject: [PATCH 01/58] fix(forge): fix stack overflow when the lib path is absolute. (#9190) * fix(forge): fix stack overflow when the lib path is absolute. * format * add test for setting absolute lib path. * remove useless code: --- crates/config/src/providers/remappings.rs | 2 +- crates/forge/tests/cli/config.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/config/src/providers/remappings.rs b/crates/config/src/providers/remappings.rs index 2e849bea4..11a17a13d 100644 --- a/crates/config/src/providers/remappings.rs +++ b/crates/config/src/providers/remappings.rs @@ -196,7 +196,7 @@ impl RemappingsProvider<'_> { fn lib_foundry_toml_remappings(&self) -> impl Iterator + '_ { self.lib_paths .iter() - .map(|p| self.root.join(p)) + .map(|p| if p.is_absolute() { self.root.join("lib") } else { self.root.join(p) }) .flat_map(foundry_toml_dirs) .inspect(|lib| { trace!("find all remappings of nested foundry.toml lib: {:?}", lib); diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index f6ec7c88e..41fb17410 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -569,6 +569,25 @@ forgetest_init!(can_detect_lib_foundry_toml, |prj, cmd| { "nested/=lib/nested-lib/lib/nested/".parse().unwrap(), ] ); + + // check if lib path is absolute, it should deteect nested lib + let mut config = cmd.config(); + config.libs = vec![nested]; + + let remappings = config.remappings.iter().cloned().map(Remapping::from).collect::>(); + similar_asserts::assert_eq!( + remappings, + vec![ + // local to the lib + "another-lib/=lib/nested-lib/lib/another-lib/custom-source-dir/".parse().unwrap(), + // global + "forge-std/=lib/forge-std/src/".parse().unwrap(), + "nested-lib/=lib/nested-lib/src/".parse().unwrap(), + // remappings local to the lib + "nested-twice/=lib/nested-lib/lib/another-lib/lib/nested-twice/".parse().unwrap(), + "nested/=lib/nested-lib/lib/nested/".parse().unwrap(), + ] + ); }); // test remappings with closer paths are prioritised From 10a8e8862ca5f9a28edebd9603f985349f536587 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Thu, 7 Nov 2024 16:44:51 +0200 Subject: [PATCH 02/58] fix(remappings): ignore remappings of root proj dirs when merging (#9258) * fix(remappings): ignore remappings of root proj dir when merging * Remove unused code * Add test * Update * Load project paths from figment --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- crates/cli/src/opts/build/core.rs | 3 +- crates/config/src/lib.rs | 17 -------- crates/config/src/providers/remappings.rs | 47 +++++++++++++++++++---- crates/forge/tests/cli/config.rs | 36 +++++++++++++++++ 4 files changed, 78 insertions(+), 25 deletions(-) diff --git a/crates/cli/src/opts/build/core.rs b/crates/cli/src/opts/build/core.rs index 58d0ace85..d25018ae8 100644 --- a/crates/cli/src/opts/build/core.rs +++ b/crates/cli/src/opts/build/core.rs @@ -181,7 +181,8 @@ impl<'a> From<&'a CoreBuildArgs> for Figment { }; // remappings should stack - let mut remappings = Remappings::new_with_remappings(args.project_paths.get_remappings()); + let mut remappings = Remappings::new_with_remappings(args.project_paths.get_remappings()) + .with_figment(&figment); remappings .extend(figment.extract_inner::>("remappings").unwrap_or_default()); figment = figment.merge(("remappings", remappings.into_inner())).merge(args); diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 916c77f9b..ec3b4e5eb 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -1091,23 +1091,6 @@ impl Config { } /// Returns all configured remappings. - /// - /// **Note:** this will add an additional `/=` remapping here, see - /// [Self::get_source_dir_remapping()] - /// - /// So that - /// - /// ```solidity - /// import "./math/math.sol"; - /// import "contracts/tokens/token.sol"; - /// ``` - /// - /// in `contracts/contract.sol` are resolved to - /// - /// ```text - /// contracts/tokens/token.sol - /// contracts/math/math.sol - /// ``` pub fn get_all_remappings(&self) -> impl Iterator + '_ { self.remappings.iter().map(|m| m.clone().into()) } diff --git a/crates/config/src/providers/remappings.rs b/crates/config/src/providers/remappings.rs index 11a17a13d..623234f94 100644 --- a/crates/config/src/providers/remappings.rs +++ b/crates/config/src/providers/remappings.rs @@ -1,7 +1,10 @@ -use crate::{foundry_toml_dirs, remappings_from_env_var, remappings_from_newline, Config}; +use crate::{ + foundry_toml_dirs, remappings_from_env_var, remappings_from_newline, utils::get_dir_remapping, + Config, +}; use figment::{ value::{Dict, Map}, - Error, Metadata, Profile, Provider, + Error, Figment, Metadata, Profile, Provider, }; use foundry_compilers::artifacts::remappings::{RelativeRemapping, Remapping}; use std::{ @@ -16,17 +19,35 @@ use std::{ pub struct Remappings { /// Remappings. remappings: Vec, + /// Source, test and script configured project dirs. + /// Remappings of these dirs from libs are ignored. + project_paths: Vec, } impl Remappings { /// Create a new `Remappings` wrapper with an empty vector. pub fn new() -> Self { - Self { remappings: Vec::new() } + Self { remappings: Vec::new(), project_paths: Vec::new() } } /// Create a new `Remappings` wrapper with a vector of remappings. pub fn new_with_remappings(remappings: Vec) -> Self { - Self { remappings } + Self { remappings, project_paths: Vec::new() } + } + + /// Extract project paths that cannot be remapped by dependencies. + pub fn with_figment(mut self, figment: &Figment) -> Self { + let mut add_project_remapping = |path: &str| { + if let Ok(path) = figment.find_value(path) { + if let Some(remapping) = path.into_string().and_then(get_dir_remapping) { + self.project_paths.push(remapping); + } + } + }; + add_project_remapping("src"); + add_project_remapping("test"); + add_project_remapping("script"); + self } /// Filters the remappings vector by name and context. @@ -47,7 +68,7 @@ impl Remappings { /// Push an element to the remappings vector, but only if it's not already present. pub fn push(&mut self, remapping: Remapping) { - if !self.remappings.iter().any(|existing| { + if self.remappings.iter().any(|existing| { // What we're doing here is filtering for ambiguous paths. For example, if we have // @prb/math/=node_modules/@prb/math/src/ as existing, and // @prb/=node_modules/@prb/ as the one being checked, @@ -55,8 +76,20 @@ impl Remappings { // having to deal with ambiguous paths which is unwanted when autodetecting remappings. existing.name.starts_with(&remapping.name) && existing.context == remapping.context }) { - self.remappings.push(remapping) - } + return; + }; + + // Ignore remappings of root project src, test or script dir. + // See . + if self + .project_paths + .iter() + .any(|project_path| remapping.name.eq_ignore_ascii_case(&project_path.name)) + { + return; + }; + + self.remappings.push(remapping); } /// Extend the remappings vector, leaving out the remappings that are already present. diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index 41fb17410..91e0781af 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -777,3 +777,39 @@ forgetest!(normalize_config_evm_version, |_prj, cmd| { let config: Config = serde_json::from_str(&output).unwrap(); assert_eq!(config.evm_version, EvmVersion::Istanbul); }); + +// Tests that root paths are properly resolved even if submodule specifies remappings for them. +// See +forgetest_init!(test_submodule_root_path_remappings, |prj, cmd| { + prj.add_script( + "BaseScript.sol", + r#" +import "forge-std/Script.sol"; + +contract BaseScript is Script { +} + "#, + ) + .unwrap(); + prj.add_script( + "MyScript.sol", + r#" +import "script/BaseScript.sol"; + +contract MyScript is BaseScript { +} + "#, + ) + .unwrap(); + + let nested = prj.paths().libraries[0].join("another-dep"); + pretty_err(&nested, fs::create_dir_all(&nested)); + let mut lib_config = Config::load_with_root(&nested); + lib_config.remappings = vec![ + Remapping::from_str("test/=test/").unwrap().into(), + Remapping::from_str("script/=script/").unwrap().into(), + ]; + let lib_toml_file = nested.join("foundry.toml"); + pretty_err(&lib_toml_file, fs::write(&lib_toml_file, lib_config.to_string_pretty().unwrap())); + cmd.forge_fuse().args(["build"]).assert_success(); +}); From adaad3da964b18abaf425c7ce263ad0896a48cb5 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 7 Nov 2024 21:43:23 +0530 Subject: [PATCH 03/58] feat(`cheatcodes`): mockCall with bytes4 data (#9267) * feat(`cheatcodes`): mockCall with bytes4 * fix * fix --- crates/cheatcodes/assets/cheatcodes.json | 80 ++++++++++++++++++++++++ crates/cheatcodes/spec/src/vm.rs | 29 +++++++++ crates/cheatcodes/src/evm/mock.rs | 67 ++++++++++++++++++++ testdata/cheats/Vm.sol | 4 ++ testdata/default/cheats/MockCall.t.sol | 4 +- 5 files changed, 182 insertions(+), 2 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 79761ae5a..747648080 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -6002,6 +6002,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "mockCallRevert_2", + "description": "Reverts a call to an address with specified revert data.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCallRevert(address callee, bytes4 data, bytes calldata revertData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCallRevert(address,bytes4,bytes)", + "selector": "0x2dfba5df", + "selectorBytes": [ + 45, + 251, + 165, + 223 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "mockCallRevert_3", + "description": "Reverts a call to an address with a specific `msg.value`, with specified revert data.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCallRevert(address callee, uint256 msgValue, bytes4 data, bytes calldata revertData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCallRevert(address,uint256,bytes4,bytes)", + "selector": "0x596c8f04", + "selectorBytes": [ + 89, + 108, + 143, + 4 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "mockCall_0", @@ -6042,6 +6082,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "mockCall_2", + "description": "Mocks a call to an address, returning specified data.\nCalldata can either be strict or a partial match, e.g. if you only\npass a Solidity selector to the expected calldata, then the entire Solidity\nfunction will be mocked.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCall(address callee, bytes4 data, bytes calldata returnData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCall(address,bytes4,bytes)", + "selector": "0x08e0c537", + "selectorBytes": [ + 8, + 224, + 197, + 55 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "mockCall_3", + "description": "Mocks a call to an address with a specific `msg.value`, returning specified data.\nCalldata match takes precedence over `msg.value` in case of ambiguity.\nOverload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`.", + "declaration": "function mockCall(address callee, uint256 msgValue, bytes4 data, bytes calldata returnData) external;", + "visibility": "external", + "mutability": "", + "signature": "mockCall(address,uint256,bytes4,bytes)", + "selector": "0xe7b36a3d", + "selectorBytes": [ + 231, + 179, + 106, + 61 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "mockCalls_0", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index ce0bc08b0..b0c0400eb 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -527,6 +527,22 @@ interface Vm { #[cheatcode(group = Evm, safety = Unsafe)] function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; + /// Mocks a call to an address, returning specified data. + /// Calldata can either be strict or a partial match, e.g. if you only + /// pass a Solidity selector to the expected calldata, then the entire Solidity + /// function will be mocked. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCall(address callee, bytes4 data, bytes calldata returnData) external; + + /// Mocks a call to an address with a specific `msg.value`, returning specified data. + /// Calldata match takes precedence over `msg.value` in case of ambiguity. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCall(address callee, uint256 msgValue, bytes4 data, bytes calldata returnData) external; + /// Mocks multiple calls to an address, returning specified data for each call. #[cheatcode(group = Evm, safety = Unsafe)] function mockCalls(address callee, bytes calldata data, bytes[] calldata returnData) external; @@ -544,6 +560,19 @@ interface Vm { function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) external; + /// Reverts a call to an address with specified revert data. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCallRevert(address callee, bytes4 data, bytes calldata revertData) external; + + /// Reverts a call to an address with a specific `msg.value`, with specified revert data. + /// + /// Overload to pass the function selector directly `token.approve.selector` instead of `abi.encodeWithSelector(token.approve.selector)`. + #[cheatcode(group = Evm, safety = Unsafe)] + function mockCallRevert(address callee, uint256 msgValue, bytes4 data, bytes calldata revertData) + external; + /// Whenever a call is made to `callee` with calldata `data`, this cheatcode instead calls /// `target` with the same calldata. This functionality is similar to a delegate call made to /// `target` contract from `callee`. diff --git a/crates/cheatcodes/src/evm/mock.rs b/crates/cheatcodes/src/evm/mock.rs index 50551d179..26aae298f 100644 --- a/crates/cheatcodes/src/evm/mock.rs +++ b/crates/cheatcodes/src/evm/mock.rs @@ -65,6 +65,39 @@ impl Cheatcode for mockCall_1Call { } } +impl Cheatcode for mockCall_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, data, returnData } = self; + let _ = make_acc_non_empty(callee, ccx.ecx)?; + + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + None, + returnData, + InstructionResult::Return, + ); + Ok(Default::default()) + } +} + +impl Cheatcode for mockCall_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, msgValue, data, returnData } = self; + ccx.ecx.load_account(*callee)?; + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + Some(msgValue), + returnData, + InstructionResult::Return, + ); + Ok(Default::default()) + } +} + impl Cheatcode for mockCalls_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, returnData } = self; @@ -104,6 +137,40 @@ impl Cheatcode for mockCallRevert_1Call { } } +impl Cheatcode for mockCallRevert_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, data, revertData } = self; + let _ = make_acc_non_empty(callee, ccx.ecx)?; + + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + None, + revertData, + InstructionResult::Revert, + ); + Ok(Default::default()) + } +} + +impl Cheatcode for mockCallRevert_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { callee, msgValue, data, revertData } = self; + let _ = make_acc_non_empty(callee, ccx.ecx)?; + + mock_call( + ccx.state, + callee, + &Bytes::from(*data), + Some(msgValue), + revertData, + InstructionResult::Revert, + ); + Ok(Default::default()) + } +} + impl Cheatcode for mockFunctionCall { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self { callee, target, data } = self; diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index b33df8f2d..6b19f26a4 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -294,8 +294,12 @@ interface Vm { function makePersistent(address[] calldata accounts) external; function mockCallRevert(address callee, bytes calldata data, bytes calldata revertData) external; function mockCallRevert(address callee, uint256 msgValue, bytes calldata data, bytes calldata revertData) external; + function mockCallRevert(address callee, bytes4 data, bytes calldata revertData) external; + function mockCallRevert(address callee, uint256 msgValue, bytes4 data, bytes calldata revertData) external; function mockCall(address callee, bytes calldata data, bytes calldata returnData) external; function mockCall(address callee, uint256 msgValue, bytes calldata data, bytes calldata returnData) external; + function mockCall(address callee, bytes4 data, bytes calldata returnData) external; + function mockCall(address callee, uint256 msgValue, bytes4 data, bytes calldata returnData) external; function mockCalls(address callee, bytes calldata data, bytes[] calldata returnData) external; function mockCalls(address callee, uint256 msgValue, bytes calldata data, bytes[] calldata returnData) external; function mockFunction(address callee, address target, bytes calldata data) external; diff --git a/testdata/default/cheats/MockCall.t.sol b/testdata/default/cheats/MockCall.t.sol index 940e5e78c..f85e9c823 100644 --- a/testdata/default/cheats/MockCall.t.sol +++ b/testdata/default/cheats/MockCall.t.sol @@ -176,7 +176,7 @@ contract MockCallTest is DSTest { Mock mock = Mock(address(100)); vm.mockCall(address(mock), abi.encodeWithSelector(mock.add.selector), abi.encode(10)); - vm.mockCall(address(mock), abi.encodeWithSelector(mock.noReturnValue.selector), abi.encode()); + vm.mockCall(address(mock), mock.noReturnValue.selector, abi.encode()); assertEq(mock.add(1, 2), 10); mock.noReturnValue(); @@ -197,7 +197,7 @@ contract MockCallRevertTest is DSTest { assertEq(target.numberA(), 1); assertEq(target.numberB(), 2); - vm.mockCallRevert(address(target), abi.encodeWithSelector(target.numberB.selector), ERROR_MESSAGE); + vm.mockCallRevert(address(target), target.numberB.selector, ERROR_MESSAGE); // post-mock assertEq(target.numberA(), 1); From c4a31a624874ab36284fca4e48d2197e43a62fbe Mon Sep 17 00:00:00 2001 From: m4rio <92288535+mario-eth@users.noreply.github.com> Date: Thu, 7 Nov 2024 19:03:24 +0200 Subject: [PATCH 04/58] feat: update to Soldeer v0.5.0 (#9281) Release 0.5.0 --- Cargo.lock | 11 ++++++----- Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bfdbb92f..f06b855af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8196,10 +8196,11 @@ dependencies = [ [[package]] name = "soldeer-commands" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf7e07f2b6002f8410811915a2f6142f2d1084764dd88cba3f4ebf22232975" +checksum = "1925813f3dd013d212fa9ad184911846f99236dbfc8a6d79c8a54dfa0bb1a948" dependencies = [ + "bon", "clap", "cliclack", "derive_more", @@ -8210,9 +8211,9 @@ dependencies = [ [[package]] name = "soldeer-core" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea249d0281f3755c3c2b095ad94a554a782cc29138f46c407b8080cfd3918996" +checksum = "434b034d411ea9d1cd9bd77fa2978a42e4c4ae486f47738a545079f11a32c879" dependencies = [ "bon", "chrono", @@ -9529,7 +9530,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 937419325..7754de503 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -278,7 +278,7 @@ semver = "1" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["arbitrary_precision"] } similar-asserts = "1.6" -soldeer-commands = "=0.4.1" +soldeer-commands = "=0.5.0" strum = "0.26" tempfile = "3.13" tikv-jemallocator = "0.6" From f3376a6e45ffacd45125e639e5f50bec0c0900be Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Fri, 8 Nov 2024 08:57:39 +0200 Subject: [PATCH 05/58] fix(`forge test`): record only test fns in test failures (#9286) --- crates/forge/bin/cmd/test/mod.rs | 12 +++++++----- crates/forge/tests/cli/test_cmd.rs | 24 ++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index c7d928a89..243ce9b22 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -20,7 +20,7 @@ use foundry_cli::{ opts::CoreBuildArgs, utils::{self, LoadConfig}, }; -use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell}; +use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell, TestFunctionExt}; use foundry_compilers::{ artifacts::output_selection::OutputSelection, compilers::{multi::MultiCompilerLanguage, CompilerSettings, Language}, @@ -935,10 +935,12 @@ fn persist_run_failures(config: &Config, outcome: &TestOutcome) { let mut filter = String::new(); let mut failures = outcome.failures().peekable(); while let Some((test_name, _)) = failures.next() { - if let Some(test_match) = test_name.split("(").next() { - filter.push_str(test_match); - if failures.peek().is_some() { - filter.push('|'); + if test_name.is_any_test() { + if let Some(test_match) = test_name.split("(").next() { + filter.push_str(test_match); + if failures.peek().is_some() { + filter.push('|'); + } } } } diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 8ce502a65..b952e19bd 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -932,6 +932,30 @@ Encountered a total of 2 failing tests, 0 tests succeeded "#]]); }); +// +forgetest_init!(should_not_record_setup_failures, |prj, cmd| { + prj.add_test( + "ReplayFailures.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract SetupFailureTest is Test { + function setUp() public { + require(2 > 1); + } + + function testA() public pure { + } +} + "#, + ) + .unwrap(); + + cmd.args(["test"]).assert_success(); + // Test failure filter should not be persisted if `setUp` failed. + assert!(!prj.root().join("cache/test-failures").exists()); +}); + // https://github.com/foundry-rs/foundry/issues/7530 forgetest_init!(should_show_precompile_labels, |prj, cmd| { prj.wipe_contracts(); From 91d33495a41530fc5ff78cb5ed26d6d17ade93e0 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Sat, 9 Nov 2024 07:40:34 +0200 Subject: [PATCH 06/58] fix(coverage): do not report empty constructors, enable reports for `receive` (#9288) fix(coverage): do not report empty constructors, enable reports for receive fn --- crates/evm/coverage/src/analysis.rs | 8 +-- crates/forge/tests/cli/coverage.rs | 92 +++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 4 deletions(-) diff --git a/crates/evm/coverage/src/analysis.rs b/crates/evm/coverage/src/analysis.rs index e5eda5262..c18ba823b 100644 --- a/crates/evm/coverage/src/analysis.rs +++ b/crates/evm/coverage/src/analysis.rs @@ -50,15 +50,15 @@ impl<'a> ContractVisitor<'a> { let name: String = node.attribute("name").ok_or_else(|| eyre::eyre!("Function has no name"))?; - // TODO(onbjerg): Figure out why we cannot find anchors for the receive function let kind: String = node.attribute("kind").ok_or_else(|| eyre::eyre!("Function has no kind"))?; - if kind == "receive" { - return Ok(()) - } match &node.body { Some(body) => { + // Do not add coverage item for constructors without statements. + if kind == "constructor" && !has_statements(body) { + return Ok(()) + } self.push_item_kind(CoverageItemKind::Function { name }, &node.src); self.visit_block(body) } diff --git a/crates/forge/tests/cli/coverage.rs b/crates/forge/tests/cli/coverage.rs index 381a31c12..0ed272ae2 100644 --- a/crates/forge/tests/cli/coverage.rs +++ b/crates/forge/tests/cli/coverage.rs @@ -1321,3 +1321,95 @@ contract AContractTest is DSTest { "#]]); }); + +// +// Test that constructor with no statements is not counted in functions coverage. +forgetest!(test_ignore_empty_constructors_coverage, |prj, cmd| { + prj.insert_ds_test(); + prj.add_source( + "AContract.sol", + r#" +contract AContract { + constructor() {} + + function increment() public {} +} + "#, + ) + .unwrap(); + + prj.add_source( + "AContractTest.sol", + r#" +import "./test.sol"; +import "./AContract.sol"; + +contract AContractTest is DSTest { + function test_constructors() public { + AContract a = new AContract(); + a.increment(); + } +} + "#, + ) + .unwrap(); + + // Assert there's only one function (`increment`) reported. + cmd.arg("coverage").args(["--summary".to_string()]).assert_success().stdout_eq(str![[r#" +... +| File | % Lines | % Statements | % Branches | % Funcs | +|-------------------|---------------|---------------|---------------|---------------| +| src/AContract.sol | 100.00% (0/0) | 100.00% (0/0) | 100.00% (0/0) | 100.00% (1/1) | +| Total | 100.00% (0/0) | 100.00% (0/0) | 100.00% (0/0) | 100.00% (1/1) | + +"#]]); +}); + +// Test coverage for `receive` functions. +forgetest!(test_receive_coverage, |prj, cmd| { + prj.insert_ds_test(); + prj.add_source( + "AContract.sol", + r#" +contract AContract { + uint256 public counter = 0; + + constructor() { + counter = 1; + } + + receive() external payable { + counter = msg.value; + } +} + "#, + ) + .unwrap(); + + prj.add_source( + "AContractTest.sol", + r#" +import "./test.sol"; +import "./AContract.sol"; + +contract AContractTest is DSTest { + function test_constructors() public { + AContract a = new AContract(); + address(a).call{value: 5}(""); + require(a.counter() == 5); + } +} + "#, + ) + .unwrap(); + + // Assert both constructor and receive functions coverage reported. + cmd.arg("coverage").args(["--summary".to_string()]).assert_success().stdout_eq(str![[r#" +... +| File | % Lines | % Statements | % Branches | % Funcs | +|-------------------|---------------|---------------|---------------|---------------| +| src/AContract.sol | 100.00% (2/2) | 100.00% (2/2) | 100.00% (0/0) | 100.00% (2/2) | +| Total | 100.00% (2/2) | 100.00% (2/2) | 100.00% (0/0) | 100.00% (2/2) | + +"#]]); +}); From bb545b1ccea9bd00eabb145008ab4fc78dfa8b47 Mon Sep 17 00:00:00 2001 From: Iain Nash Date: Sat, 9 Nov 2024 05:10:11 -0500 Subject: [PATCH 07/58] Make fs read cheatcodes views (#9289) --- crates/cheatcodes/assets/cheatcodes.json | 40 ++++++++++++------------ crates/cheatcodes/spec/src/vm.rs | 20 ++++++------ testdata/cheats/Vm.sol | 20 ++++++------ 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 747648080..41797106d 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -4584,9 +4584,9 @@ "func": { "id": "exists", "description": "Returns true if the given path points to an existing entity, else returns false.", - "declaration": "function exists(string calldata path) external returns (bool result);", + "declaration": "function exists(string calldata path) external view returns (bool result);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "exists(string)", "selector": "0x261a323e", "selectorBytes": [ @@ -5304,9 +5304,9 @@ "func": { "id": "getBroadcast", "description": "Returns the most recent broadcast for the given contract on `chainId` matching `txType`.\nFor example:\nThe most recent deployment can be fetched by passing `txType` as `CREATE` or `CREATE2`.\nThe most recent call can be fetched by passing `txType` as `CALL`.", - "declaration": "function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary memory);", + "declaration": "function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary memory);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getBroadcast(string,uint64,uint8)", "selector": "0x3dc90cb3", "selectorBytes": [ @@ -5324,9 +5324,9 @@ "func": { "id": "getBroadcasts_0", "description": "Returns all broadcasts for the given contract on `chainId` with the specified `txType`.\nSorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.", - "declaration": "function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary[] memory);", + "declaration": "function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary[] memory);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getBroadcasts(string,uint64,uint8)", "selector": "0xf7afe919", "selectorBytes": [ @@ -5344,9 +5344,9 @@ "func": { "id": "getBroadcasts_1", "description": "Returns all broadcasts for the given contract on `chainId`.\nSorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber.", - "declaration": "function getBroadcasts(string memory contractName, uint64 chainId) external returns (BroadcastTxSummary[] memory);", + "declaration": "function getBroadcasts(string memory contractName, uint64 chainId) external view returns (BroadcastTxSummary[] memory);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getBroadcasts(string,uint64)", "selector": "0xf2fa4a26", "selectorBytes": [ @@ -5404,9 +5404,9 @@ "func": { "id": "getDeployment_0", "description": "Returns the most recent deployment for the current `chainId`.", - "declaration": "function getDeployment(string memory contractName) external returns (address deployedAddress);", + "declaration": "function getDeployment(string memory contractName) external view returns (address deployedAddress);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getDeployment(string)", "selector": "0xa8091d97", "selectorBytes": [ @@ -5424,9 +5424,9 @@ "func": { "id": "getDeployment_1", "description": "Returns the most recent deployment for the given contract on `chainId`", - "declaration": "function getDeployment(string memory contractName, uint64 chainId) external returns (address deployedAddress);", + "declaration": "function getDeployment(string memory contractName, uint64 chainId) external view returns (address deployedAddress);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getDeployment(string,uint64)", "selector": "0x0debd5d6", "selectorBytes": [ @@ -5444,9 +5444,9 @@ "func": { "id": "getDeployments", "description": "Returns all deployments for the given contract on `chainId`\nSorted in descending order of deployment time i.e descending order of BroadcastTxSummary.blockNumber.\nThe most recent deployment is the first element, and the oldest is the last.", - "declaration": "function getDeployments(string memory contractName, uint64 chainId) external returns (address[] memory deployedAddresses);", + "declaration": "function getDeployments(string memory contractName, uint64 chainId) external view returns (address[] memory deployedAddresses);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "getDeployments(string,uint64)", "selector": "0x74e133dd", "selectorBytes": [ @@ -5684,9 +5684,9 @@ "func": { "id": "isDir", "description": "Returns true if the path exists on disk and is pointing at a directory, else returns false.", - "declaration": "function isDir(string calldata path) external returns (bool result);", + "declaration": "function isDir(string calldata path) external view returns (bool result);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "isDir(string)", "selector": "0x7d15d019", "selectorBytes": [ @@ -5704,9 +5704,9 @@ "func": { "id": "isFile", "description": "Returns true if the path exists on disk and is pointing at a regular file, else returns false.", - "declaration": "function isFile(string calldata path) external returns (bool result);", + "declaration": "function isFile(string calldata path) external view returns (bool result);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "isFile(string)", "selector": "0xe0eb04d4", "selectorBytes": [ @@ -9892,9 +9892,9 @@ "func": { "id": "unixTime", "description": "Returns the time since unix epoch in milliseconds.", - "declaration": "function unixTime() external returns (uint256 milliseconds);", + "declaration": "function unixTime() external view returns (uint256 milliseconds);", "visibility": "external", - "mutability": "", + "mutability": "view", "signature": "unixTime()", "selector": "0x625387dc", "selectorBytes": [ diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index b0c0400eb..3c11cd53a 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -1582,7 +1582,7 @@ interface Vm { /// Returns true if the given path points to an existing entity, else returns false. #[cheatcode(group = Filesystem)] - function exists(string calldata path) external returns (bool result); + function exists(string calldata path) external view returns (bool result); /// Given a path, query the file system to get information about a file, directory, etc. #[cheatcode(group = Filesystem)] @@ -1590,11 +1590,11 @@ interface Vm { /// Returns true if the path exists on disk and is pointing at a directory, else returns false. #[cheatcode(group = Filesystem)] - function isDir(string calldata path) external returns (bool result); + function isDir(string calldata path) external view returns (bool result); /// Returns true if the path exists on disk and is pointing at a regular file, else returns false. #[cheatcode(group = Filesystem)] - function isFile(string calldata path) external returns (bool result); + function isFile(string calldata path) external view returns (bool result); /// Get the path of the current project root. #[cheatcode(group = Filesystem)] @@ -1602,7 +1602,7 @@ interface Vm { /// Returns the time since unix epoch in milliseconds. #[cheatcode(group = Filesystem)] - function unixTime() external returns (uint256 milliseconds); + function unixTime() external view returns (uint256 milliseconds); // -------- Reading and writing -------- @@ -1732,27 +1732,27 @@ interface Vm { /// /// The most recent call can be fetched by passing `txType` as `CALL`. #[cheatcode(group = Filesystem)] - function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary memory); + function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary memory); /// Returns all broadcasts for the given contract on `chainId` with the specified `txType`. /// /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber. #[cheatcode(group = Filesystem)] - function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary[] memory); + function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary[] memory); /// Returns all broadcasts for the given contract on `chainId`. /// /// Sorted such that the most recent broadcast is the first element, and the oldest is the last. i.e descending order of BroadcastTxSummary.blockNumber. #[cheatcode(group = Filesystem)] - function getBroadcasts(string memory contractName, uint64 chainId) external returns (BroadcastTxSummary[] memory); + function getBroadcasts(string memory contractName, uint64 chainId) external view returns (BroadcastTxSummary[] memory); /// Returns the most recent deployment for the current `chainId`. #[cheatcode(group = Filesystem)] - function getDeployment(string memory contractName) external returns (address deployedAddress); + function getDeployment(string memory contractName) external view returns (address deployedAddress); /// Returns the most recent deployment for the given contract on `chainId` #[cheatcode(group = Filesystem)] - function getDeployment(string memory contractName, uint64 chainId) external returns (address deployedAddress); + function getDeployment(string memory contractName, uint64 chainId) external view returns (address deployedAddress); /// Returns all deployments for the given contract on `chainId` /// @@ -1760,7 +1760,7 @@ interface Vm { /// /// The most recent deployment is the first element, and the oldest is the last. #[cheatcode(group = Filesystem)] - function getDeployments(string memory contractName, uint64 chainId) external returns (address[] memory deployedAddresses); + function getDeployments(string memory contractName, uint64 chainId) external view returns (address[] memory deployedAddresses); // -------- Foreign Function Interface -------- diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 6b19f26a4..d3a377f40 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -223,7 +223,7 @@ interface Vm { function envUint(string calldata name, string calldata delim) external view returns (uint256[] memory value); function etch(address target, bytes calldata newRuntimeBytecode) external; function eth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] memory topics) external returns (EthGetLogs[] memory logs); - function exists(string calldata path) external returns (bool result); + function exists(string calldata path) external view returns (bool result); function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data) external; function expectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytes calldata data, uint64 count) external; function expectCall(address callee, bytes calldata data) external; @@ -259,14 +259,14 @@ interface Vm { function getBlobhashes() external view returns (bytes32[] memory hashes); function getBlockNumber() external view returns (uint256 height); function getBlockTimestamp() external view returns (uint256 timestamp); - function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary memory); - function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external returns (BroadcastTxSummary[] memory); - function getBroadcasts(string memory contractName, uint64 chainId) external returns (BroadcastTxSummary[] memory); + function getBroadcast(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary memory); + function getBroadcasts(string memory contractName, uint64 chainId, BroadcastTxType txType) external view returns (BroadcastTxSummary[] memory); + function getBroadcasts(string memory contractName, uint64 chainId) external view returns (BroadcastTxSummary[] memory); function getCode(string calldata artifactPath) external view returns (bytes memory creationBytecode); function getDeployedCode(string calldata artifactPath) external view returns (bytes memory runtimeBytecode); - function getDeployment(string memory contractName) external returns (address deployedAddress); - function getDeployment(string memory contractName, uint64 chainId) external returns (address deployedAddress); - function getDeployments(string memory contractName, uint64 chainId) external returns (address[] memory deployedAddresses); + function getDeployment(string memory contractName) external view returns (address deployedAddress); + function getDeployment(string memory contractName, uint64 chainId) external view returns (address deployedAddress); + function getDeployments(string memory contractName, uint64 chainId) external view returns (address[] memory deployedAddresses); function getFoundryVersion() external view returns (string memory version); function getLabel(address account) external view returns (string memory currentLabel); function getMappingKeyAndParentOf(address target, bytes32 elementSlot) external returns (bool found, bytes32 key, bytes32 parent); @@ -278,8 +278,8 @@ interface Vm { function getWallets() external returns (address[] memory wallets); function indexOf(string calldata input, string calldata key) external pure returns (uint256); function isContext(ForgeContext context) external view returns (bool result); - function isDir(string calldata path) external returns (bool result); - function isFile(string calldata path) external returns (bool result); + function isDir(string calldata path) external view returns (bool result); + function isFile(string calldata path) external view returns (bool result); function isPersistent(address account) external view returns (bool persistent); function keyExists(string calldata json, string calldata key) external view returns (bool); function keyExistsJson(string calldata json, string calldata key) external view returns (bool); @@ -488,7 +488,7 @@ interface Vm { function trim(string calldata input) external pure returns (string memory output); function tryFfi(string[] calldata commandInput) external returns (FfiResult memory result); function txGasPrice(uint256 newGasPrice) external; - function unixTime() external returns (uint256 milliseconds); + function unixTime() external view returns (uint256 milliseconds); function warp(uint256 newTimestamp) external; function writeFile(string calldata path, string calldata data) external; function writeFileBinary(string calldata path, bytes calldata data) external; From 48abbd95e4fd7ea55ee4f1e9b1a590d25d8aab37 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Sat, 9 Nov 2024 14:18:28 +0200 Subject: [PATCH 08/58] chore: fix clippy (#9291) --- crates/common/src/compile.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/common/src/compile.rs b/crates/common/src/compile.rs index d504e1688..1af4d5db6 100644 --- a/crates/common/src/compile.rs +++ b/crates/common/src/compile.rs @@ -382,7 +382,7 @@ fn contract_size(artifact: &T, initcode: bool) -> Option { BytecodeObject::Unlinked(unlinked) => { // we don't need to account for placeholders here, because library placeholders take up // 40 characters: `__$$__` which is the same as a 20byte address in hex. - let mut size = unlinked.as_bytes().len(); + let mut size = unlinked.len(); if unlinked.starts_with("0x") { size -= 2; } From 9df593939b995b08eee7dbab585ec368f65c8116 Mon Sep 17 00:00:00 2001 From: feynman <14007952+feynman-x@users.noreply.github.com> Date: Sun, 10 Nov 2024 00:23:14 +0800 Subject: [PATCH 09/58] feat(anvil): add `anvil_getIntervalMining` API (#9290) * feat: add anvil_get_interval_mine method * refactor: keep consistent naming --------- Co-authored-by: Your Name Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> --- crates/anvil/core/src/eth/mod.rs | 4 ++++ crates/anvil/src/eth/api.rs | 9 +++++++++ crates/anvil/src/eth/miner.rs | 7 +++++-- crates/anvil/tests/it/anvil.rs | 3 +++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index 73c133b2c..38691ba0d 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -394,6 +394,10 @@ pub enum EthRequest { )] SetIntervalMining(u64), + /// Gets the current mining behavior + #[cfg_attr(feature = "serde", serde(rename = "anvil_getIntervalMing", with = "empty_params"))] + GetIntervalMining(()), + /// Removes transactions from the pool #[cfg_attr( feature = "serde", diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 81990d755..e5210b0c2 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -326,6 +326,7 @@ impl EthApi { EthRequest::SetIntervalMining(interval) => { self.anvil_set_interval_mining(interval).to_rpc_result() } + EthRequest::GetIntervalMining(()) => self.anvil_get_interval_ming().to_rpc_result(), EthRequest::DropTransaction(tx) => { self.anvil_drop_transaction(tx).await.to_rpc_result() } @@ -1665,6 +1666,14 @@ impl EthApi { Ok(self.miner.is_auto_mine()) } + /// Returns the value of mining interval, if set. + /// + /// Handler for ETH RPC call: `anvil_getIntervalMing` + pub fn anvil_get_interval_ming(&self) -> Result> { + node_info!("anvil_getIntervalMining"); + Ok(self.miner.get_interval()) + } + /// Enables or disables, based on the single boolean argument, the automatic mining of new /// blocks with each new transaction submitted to the network. /// diff --git a/crates/anvil/src/eth/miner.rs b/crates/anvil/src/eth/miner.rs index defb6624a..90c455090 100644 --- a/crates/anvil/src/eth/miner.rs +++ b/crates/anvil/src/eth/miner.rs @@ -64,9 +64,12 @@ impl Miner { matches!(*mode, MiningMode::Auto(_)) } - pub fn is_interval(&self) -> bool { + pub fn get_interval(&self) -> Option { let mode = self.mode.read(); - matches!(*mode, MiningMode::FixedBlockTime(_)) + if let MiningMode::FixedBlockTime(ref mm) = *mode { + return Some(mm.interval.period().as_secs()) + } + None } /// Sets the mining mode to operate in diff --git a/crates/anvil/tests/it/anvil.rs b/crates/anvil/tests/it/anvil.rs index 5a952da6b..17b94f041 100644 --- a/crates/anvil/tests/it/anvil.rs +++ b/crates/anvil/tests/it/anvil.rs @@ -12,12 +12,14 @@ async fn test_can_change_mining_mode() { let provider = handle.http_provider(); assert!(api.anvil_get_auto_mine().unwrap()); + assert!(api.anvil_get_interval_ming().unwrap().is_none()); let num = provider.get_block_number().await.unwrap(); assert_eq!(num, 0); api.anvil_set_interval_mining(1).unwrap(); assert!(!api.anvil_get_auto_mine().unwrap()); + assert!(matches!(api.anvil_get_interval_ming().unwrap(), Some(1))); // changing the mining mode will instantly mine a new block tokio::time::sleep(std::time::Duration::from_millis(500)).await; let num = provider.get_block_number().await.unwrap(); @@ -30,6 +32,7 @@ async fn test_can_change_mining_mode() { // assert that no block is mined when the interval is set to 0 api.anvil_set_interval_mining(0).unwrap(); assert!(!api.anvil_get_auto_mine().unwrap()); + assert!(api.anvil_get_interval_ming().unwrap().is_none()); tokio::time::sleep(std::time::Duration::from_millis(1000)).await; let num = provider.get_block_number().await.unwrap(); assert_eq!(num, 1); From d2f92bc35ec67e4db01ea00f5edf439eb92eee5e Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Sat, 9 Nov 2024 17:26:19 +0100 Subject: [PATCH 10/58] chore(`common::shell`): finish implementation + enforce in `clippy` (#9268) * enforce for script and verify crates * complete and enforce common shell * permit eprintln! due to circular dependency outside of common path * avoid code duplication --- Cargo.lock | 1 + clippy.toml | 14 ++++---- crates/anvil/tests/it/eip4844.rs | 2 ++ crates/anvil/tests/it/pubsub.rs | 1 + crates/cast/bin/main.rs | 32 +++++++++++++---- crates/cheatcodes/spec/src/lib.rs | 1 + crates/cheatcodes/src/fs.rs | 4 +-- crates/cheatcodes/src/lib.rs | 4 +++ crates/cli/src/utils/cmd.rs | 17 +++++---- crates/common/fmt/src/dynamic.rs | 12 ------- crates/common/fmt/src/lib.rs | 4 +-- crates/common/src/abi.rs | 4 +-- crates/common/src/compile.rs | 18 +++++----- crates/common/src/ens.rs | 4 ++- crates/common/src/selectors.rs | 33 ++++++++--------- crates/common/src/term.rs | 6 ++-- crates/config/src/lib.rs | 4 +++ crates/debugger/src/debugger.rs | 2 +- crates/debugger/src/lib.rs | 3 ++ crates/doc/Cargo.toml | 1 + crates/doc/src/builder.rs | 2 +- crates/doc/src/lib.rs | 3 ++ crates/evm/coverage/src/lib.rs | 5 ++- crates/evm/traces/src/identifier/etherscan.rs | 2 +- crates/evm/traces/src/lib.rs | 3 ++ crates/forge/bin/cmd/install.rs | 6 ++-- crates/forge/bin/cmd/test/mod.rs | 2 +- crates/script/src/execute.rs | 2 +- crates/script/src/runner.rs | 3 +- crates/script/src/simulate.rs | 6 ++-- crates/script/src/verify.rs | 25 ++++++------- crates/test-utils/src/lib.rs | 3 ++ crates/test-utils/src/rpc.rs | 4 +-- crates/test-utils/src/util.rs | 26 +++++++------- crates/verify/src/bytecode.rs | 19 +++++----- crates/verify/src/etherscan/mod.rs | 36 ++++++++++--------- crates/verify/src/sourcify.rs | 12 +++---- crates/verify/src/utils.rs | 13 +++---- crates/verify/src/verify.rs | 9 +++-- 39 files changed, 188 insertions(+), 160 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f06b855af..a58b40977 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3424,6 +3424,7 @@ dependencies = [ "derive_more", "eyre", "forge-fmt", + "foundry-common", "foundry-compilers", "foundry-config", "itertools 0.13.0", diff --git a/clippy.toml b/clippy.toml index 3e45486a8..b1756dfd9 100644 --- a/clippy.toml +++ b/clippy.toml @@ -3,10 +3,10 @@ msrv = "1.80" # so it is safe to ignore it as well ignore-interior-mutability = ["bytes::Bytes", "alloy_primitives::Bytes"] -# disallowed-macros = [ -# # See `foundry_common::shell` -# { path = "std::print", reason = "use `sh_print` or similar macros instead" }, -# { path = "std::eprint", reason = "use `sh_eprint` or similar macros instead" }, -# { path = "std::println", reason = "use `sh_println` or similar macros instead" }, -# { path = "std::eprintln", reason = "use `sh_eprintln` or similar macros instead" }, -# ] +disallowed-macros = [ + # See `foundry_common::shell` + { path = "std::print", reason = "use `sh_print` or similar macros instead" }, + { path = "std::eprint", reason = "use `sh_eprint` or similar macros instead" }, + { path = "std::println", reason = "use `sh_println` or similar macros instead" }, + { path = "std::eprintln", reason = "use `sh_eprintln` or similar macros instead" }, +] diff --git a/crates/anvil/tests/it/eip4844.rs b/crates/anvil/tests/it/eip4844.rs index a4243ce15..2b965087b 100644 --- a/crates/anvil/tests/it/eip4844.rs +++ b/crates/anvil/tests/it/eip4844.rs @@ -205,6 +205,7 @@ async fn can_check_blob_fields_on_genesis() { assert_eq!(block.header.excess_blob_gas, Some(0)); } +#[allow(clippy::disallowed_macros)] #[tokio::test(flavor = "multi_thread")] async fn can_correctly_estimate_blob_gas_with_recommended_fillers() { let node_config = NodeConfig::test().with_hardfork(Some(EthereumHardfork::Cancun.into())); @@ -247,6 +248,7 @@ async fn can_correctly_estimate_blob_gas_with_recommended_fillers() { ); } +#[allow(clippy::disallowed_macros)] #[tokio::test(flavor = "multi_thread")] async fn can_correctly_estimate_blob_gas_with_recommended_fillers_with_signer() { let node_config = NodeConfig::test().with_hardfork(Some(EthereumHardfork::Cancun.into())); diff --git a/crates/anvil/tests/it/pubsub.rs b/crates/anvil/tests/it/pubsub.rs index a343f7c70..ecfb9b100 100644 --- a/crates/anvil/tests/it/pubsub.rs +++ b/crates/anvil/tests/it/pubsub.rs @@ -247,6 +247,7 @@ async fn test_subscriptions() { assert_eq!(blocks, vec![1, 2, 3]) } +#[allow(clippy::disallowed_macros)] #[tokio::test(flavor = "multi_thread")] async fn test_sub_new_heads_fast() { let (api, handle) = spawn(NodeConfig::test()).await; diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index 851fcfd77..cdeaad2d2 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate tracing; +use alloy_dyn_abi::DynSolValue; use alloy_primitives::{eip191_hash_message, hex, keccak256, Address, B256}; use alloy_provider::Provider; use alloy_rpc_types::{BlockId, BlockNumberOrTag::Latest}; @@ -12,7 +13,7 @@ use foundry_cli::{handler, utils}; use foundry_common::{ abi::get_event, ens::{namehash, ProviderEnsExt}, - fmt::{format_uint_exp, print_tokens}, + fmt::{format_tokens, format_tokens_raw, format_uint_exp}, fs, selectors::{ decode_calldata, decode_event_topic, decode_function_selector, decode_selectors, @@ -135,11 +136,11 @@ async fn main_args(args: CastArgs) -> Result<()> { } CastSubcommand::ParseUnits { value, unit } => { let value = stdin::unwrap_line(value)?; - println!("{}", SimpleCast::parse_units(&value, unit)?); + sh_println!("{}", SimpleCast::parse_units(&value, unit)?)?; } CastSubcommand::FormatUnits { value, unit } => { let value = stdin::unwrap_line(value)?; - println!("{}", SimpleCast::format_units(&value, unit)?); + sh_println!("{}", SimpleCast::format_units(&value, unit)?)?; } CastSubcommand::FromWei { value, unit } => { let value = stdin::unwrap_line(value)?; @@ -189,7 +190,7 @@ async fn main_args(args: CastArgs) -> Result<()> { // ABI encoding & decoding CastSubcommand::AbiDecode { sig, calldata, input } => { let tokens = SimpleCast::abi_decode(&sig, &calldata, input)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::AbiEncode { sig, packed, args } => { if !packed { @@ -200,14 +201,14 @@ async fn main_args(args: CastArgs) -> Result<()> { } CastSubcommand::CalldataDecode { sig, calldata } => { let tokens = SimpleCast::calldata_decode(&sig, &calldata, true)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::CalldataEncode { sig, args } => { sh_println!("{}", SimpleCast::calldata_encode(sig, &args)?)?; } CastSubcommand::StringDecode { data } => { let tokens = SimpleCast::calldata_decode("Any(string)", &data, true)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::Interface(cmd) => cmd.run().await?, CastSubcommand::CreationCode(cmd) => cmd.run().await?, @@ -482,7 +483,7 @@ async fn main_args(args: CastArgs) -> Result<()> { }; let tokens = SimpleCast::calldata_decode(sig, &calldata, true)?; - print_tokens(&tokens, shell::is_json()) + print_tokens(&tokens); } CastSubcommand::FourByteEvent { topic } => { let topic = stdin::unwrap_line(topic)?; @@ -618,5 +619,22 @@ async fn main_args(args: CastArgs) -> Result<()> { sh_println!("{}", SimpleCast::decode_eof(&eof)?)? } }; + + /// Prints slice of tokens using [`format_tokens`] or [`format_tokens_raw`] depending whether + /// the shell is in JSON mode. + /// + /// This is included here to avoid a cyclic dependency between `fmt` and `common`. + fn print_tokens(tokens: &[DynSolValue]) { + if shell::is_json() { + let tokens: Vec = format_tokens_raw(tokens).collect(); + let _ = sh_println!("{}", serde_json::to_string_pretty(&tokens).unwrap()); + } else { + let tokens = format_tokens(tokens); + tokens.for_each(|t| { + let _ = sh_println!("{t}"); + }); + } + } + Ok(()) } diff --git a/crates/cheatcodes/spec/src/lib.rs b/crates/cheatcodes/spec/src/lib.rs index eae2ae0ee..5692dfc48 100644 --- a/crates/cheatcodes/spec/src/lib.rs +++ b/crates/cheatcodes/spec/src/lib.rs @@ -103,6 +103,7 @@ impl Cheatcodes<'static> { } #[cfg(test)] +#[allow(clippy::disallowed_macros)] mod tests { use super::*; use std::{fs, path::Path}; diff --git a/crates/cheatcodes/src/fs.rs b/crates/cheatcodes/src/fs.rs index 04af101eb..e52aaa688 100644 --- a/crates/cheatcodes/src/fs.rs +++ b/crates/cheatcodes/src/fs.rs @@ -620,11 +620,11 @@ fn prompt( match rx.recv_timeout(timeout) { Ok(res) => res.map_err(|err| { - println!(); + let _ = sh_println!(); err.to_string().into() }), Err(_) => { - println!(); + let _ = sh_eprintln!(); Err("Prompt timed out".into()) } } diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index ff93b8336..95d04cab8 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -6,8 +6,12 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![allow(elided_lifetimes_in_paths)] // Cheats context uses 3 lifetimes +#[macro_use] +extern crate foundry_common; + #[macro_use] pub extern crate foundry_cheatcodes_spec as spec; + #[macro_use] extern crate tracing; diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 9852f53f1..2ebdc2539 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -128,9 +128,8 @@ pub fn needs_setup(abi: &JsonAbi) -> bool { for setup_fn in setup_fns.iter() { if setup_fn.name != "setUp" { - println!( - "{} Found invalid setup function \"{}\" did you mean \"setUp()\"?", - "Warning:".yellow().bold(), + let _ = sh_warn!( + "Found invalid setup function \"{}\" did you mean \"setUp()\"?", setup_fn.signature() ); } @@ -450,19 +449,19 @@ pub async fn print_traces( ) -> Result<()> { let traces = result.traces.as_mut().expect("No traces found"); - println!("Traces:"); + sh_println!("Traces:")?; for (_, arena) in traces { decode_trace_arena(arena, decoder).await?; - println!("{}", render_trace_arena_with_bytecodes(arena, verbose)); + sh_println!("{}", render_trace_arena_with_bytecodes(arena, verbose))?; } - println!(); + sh_println!()?; if result.success { - println!("{}", "Transaction successfully executed.".green()); + sh_println!("{}", "Transaction successfully executed.".green())?; } else { - println!("{}", "Transaction failed.".red()); + sh_err!("Transaction failed.")?; } - println!("Gas used: {}", result.gas_used); + sh_println!("Gas used: {}", result.gas_used)?; Ok(()) } diff --git a/crates/common/fmt/src/dynamic.rs b/crates/common/fmt/src/dynamic.rs index 498d209f7..2ba40286d 100644 --- a/crates/common/fmt/src/dynamic.rs +++ b/crates/common/fmt/src/dynamic.rs @@ -132,18 +132,6 @@ pub fn format_tokens_raw(tokens: &[DynSolValue]) -> impl Iterator tokens.iter().map(format_token_raw) } -/// Prints slice of tokens using [`format_tokens`] or [`format_tokens_raw`] depending on `json` -/// parameter. -pub fn print_tokens(tokens: &[DynSolValue], json: bool) { - if json { - let tokens: Vec = format_tokens_raw(tokens).collect(); - println!("{}", serde_json::to_string_pretty(&tokens).unwrap()); - } else { - let tokens = format_tokens(tokens); - tokens.for_each(|t| println!("{t}")); - } -} - /// Pretty-prints the given value into a string suitable for user output. pub fn format_token(value: &DynSolValue) -> String { DynValueDisplay::new(value, false).to_string() diff --git a/crates/common/fmt/src/lib.rs b/crates/common/fmt/src/lib.rs index f6f792e99..b76016cd4 100644 --- a/crates/common/fmt/src/lib.rs +++ b/crates/common/fmt/src/lib.rs @@ -4,9 +4,7 @@ mod console; pub use console::{console_format, ConsoleFmt, FormatSpec}; mod dynamic; -pub use dynamic::{ - format_token, format_token_raw, format_tokens, format_tokens_raw, parse_tokens, print_tokens, -}; +pub use dynamic::{format_token, format_token_raw, format_tokens, format_tokens_raw, parse_tokens}; mod exp; pub use exp::{format_int_exp, format_uint_exp, to_exp_notation}; diff --git a/crates/common/src/abi.rs b/crates/common/src/abi.rs index bcf82b1cd..de9b36219 100644 --- a/crates/common/src/abi.rs +++ b/crates/common/src/abi.rs @@ -146,9 +146,9 @@ pub fn find_source( Ok(source) } else { let implementation = metadata.implementation.unwrap(); - println!( + sh_println!( "Contract at {address} is a proxy, trying to fetch source at {implementation}..." - ); + )?; match find_source(client, implementation).await { impl_source @ Ok(_) => impl_source, Err(e) => { diff --git a/crates/common/src/compile.rs b/crates/common/src/compile.rs index 1af4d5db6..4c7e7ba0f 100644 --- a/crates/common/src/compile.rs +++ b/crates/common/src/compile.rs @@ -127,7 +127,7 @@ impl ProjectCompiler { pub fn compile(mut self, project: &Project) -> Result> { // TODO: Avoid process::exit if !project.paths.has_input_files() && self.files.is_empty() { - println!("Nothing to compile"); + sh_println!("Nothing to compile")?; // nothing to do here std::process::exit(0); } @@ -182,10 +182,10 @@ impl ProjectCompiler { if !quiet { if output.is_unchanged() { - println!("No files changed, compilation skipped"); + sh_println!("No files changed, compilation skipped")?; } else { // print the compiler output / warnings - println!("{output}"); + sh_println!("{output}")?; } self.handle_output(&output); @@ -206,12 +206,14 @@ impl ProjectCompiler { artifacts.entry(version).or_default().push(name); } for (version, names) in artifacts { - println!( + let _ = sh_println!( " compiler version: {}.{}.{}", - version.major, version.minor, version.patch + version.major, + version.minor, + version.patch ); for name in names { - println!(" - {name}"); + let _ = sh_println!(" - {name}"); } } } @@ -219,7 +221,7 @@ impl ProjectCompiler { if print_sizes { // add extra newline if names were already printed if print_names { - println!(); + let _ = sh_println!(); } let mut size_report = SizeReport { contracts: BTreeMap::new() }; @@ -252,7 +254,7 @@ impl ProjectCompiler { .insert(name, ContractInfo { runtime_size, init_size, is_dev_contract }); } - println!("{size_report}"); + let _ = sh_println!("{size_report}"); // TODO: avoid process::exit // exit with error if any contract exceeds the size limit, excluding test contracts. diff --git a/crates/common/src/ens.rs b/crates/common/src/ens.rs index f84ea84ce..1c4eadeac 100644 --- a/crates/common/src/ens.rs +++ b/crates/common/src/ens.rs @@ -123,7 +123,9 @@ pub trait ProviderEnsExt> { .call() .await .map_err(EnsError::Resolve) - .inspect_err(|e| eprintln!("{e:?}"))? + .inspect_err(|e| { + let _ = sh_eprintln!("{e:?}"); + })? ._0; Ok(addr) } diff --git a/crates/common/src/selectors.rs b/crates/common/src/selectors.rs index 23a272a2a..cd4e2ffd0 100644 --- a/crates/common/src/selectors.rs +++ b/crates/common/src/selectors.rs @@ -492,24 +492,20 @@ pub struct SelectorImportResponse { impl SelectorImportResponse { /// Print info about the functions which were uploaded or already known pub fn describe(&self) { - self.result - .function - .imported - .iter() - .for_each(|(k, v)| println!("Imported: Function {k}: {v}")); - self.result.event.imported.iter().for_each(|(k, v)| println!("Imported: Event {k}: {v}")); - self.result - .function - .duplicated - .iter() - .for_each(|(k, v)| println!("Duplicated: Function {k}: {v}")); - self.result - .event - .duplicated - .iter() - .for_each(|(k, v)| println!("Duplicated: Event {k}: {v}")); - - println!("Selectors successfully uploaded to OpenChain"); + self.result.function.imported.iter().for_each(|(k, v)| { + let _ = sh_println!("Imported: Function {k}: {v}"); + }); + self.result.event.imported.iter().for_each(|(k, v)| { + let _ = sh_println!("Imported: Event {k}: {v}"); + }); + self.result.function.duplicated.iter().for_each(|(k, v)| { + let _ = sh_println!("Duplicated: Function {k}: {v}"); + }); + self.result.event.duplicated.iter().for_each(|(k, v)| { + let _ = sh_println!("Duplicated: Event {k}: {v}"); + }); + + let _ = sh_println!("Selectors successfully uploaded to OpenChain"); } } @@ -579,6 +575,7 @@ pub fn parse_signatures(tokens: Vec) -> ParsedSignatures { } #[cfg(test)] +#[allow(clippy::disallowed_macros)] #[allow(clippy::needless_return)] mod tests { use super::*; diff --git a/crates/common/src/term.rs b/crates/common/src/term.rs index 4753b1e41..ead39b5fa 100644 --- a/crates/common/src/term.rs +++ b/crates/common/src/term.rs @@ -72,7 +72,7 @@ impl Spinner { let indicator = self.indicator[self.idx % self.indicator.len()].green(); let indicator = Paint::new(format!("[{indicator}]")).bold(); - print!("\r\x33[2K\r{indicator} {}", self.message); + let _ = sh_print!("\r\x33[2K\r{indicator} {}", self.message); io::stdout().flush().unwrap(); self.idx = self.idx.wrapping_add(1); @@ -112,11 +112,11 @@ impl SpinnerReporter { Ok(SpinnerMsg::Msg(msg)) => { spinner.message(msg); // new line so past messages are not overwritten - println!(); + let _ = sh_println!(); } Ok(SpinnerMsg::Shutdown(ack)) => { // end with a newline - println!(); + let _ = sh_println!(); let _ = ack.send(()); break } diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index ec3b4e5eb..986a0181d 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -933,6 +933,7 @@ impl Config { /// it's missing, unless the `offline` flag is enabled, in which case an error is thrown. /// /// If `solc` is [`SolcReq::Local`] then this will ensure that the path exists. + #[allow(clippy::disallowed_macros)] fn ensure_solc(&self) -> Result, SolcError> { if self.eof { let (tx, rx) = mpsc::channel(); @@ -957,12 +958,14 @@ impl Config { return match rx.recv_timeout(Duration::from_secs(1)) { Ok(res) => res, Err(RecvTimeoutError::Timeout) => { + // `sh_warn!` is a circular dependency, preventing us from using it here. eprintln!( "{}", yansi::Paint::yellow( "Pulling Docker image for eof-solc, this might take some time..." ) ); + rx.recv().expect("sender dropped") } Err(RecvTimeoutError::Disconnected) => panic!("sender dropped"), @@ -4880,6 +4883,7 @@ mod tests { } // a test to print the config, mainly used to update the example config in the README + #[allow(clippy::disallowed_macros)] #[test] #[ignore] fn print_config() { diff --git a/crates/debugger/src/debugger.rs b/crates/debugger/src/debugger.rs index 0e4de437c..469225118 100644 --- a/crates/debugger/src/debugger.rs +++ b/crates/debugger/src/debugger.rs @@ -48,7 +48,7 @@ impl Debugger { let code = match self.try_run_tui() { Ok(ExitReason::CharExit) => 0, Err(e) => { - println!("{e}"); + let _ = sh_eprintln!("{e}"); 1 } }; diff --git a/crates/debugger/src/lib.rs b/crates/debugger/src/lib.rs index aa561973c..67c9ee984 100644 --- a/crates/debugger/src/lib.rs +++ b/crates/debugger/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/doc/Cargo.toml b/crates/doc/Cargo.toml index 00223eb27..95e26df17 100644 --- a/crates/doc/Cargo.toml +++ b/crates/doc/Cargo.toml @@ -15,6 +15,7 @@ workspace = true [dependencies] forge-fmt.workspace = true +foundry-common.workspace = true foundry-compilers.workspace = true foundry-config.workspace = true diff --git a/crates/doc/src/builder.rs b/crates/doc/src/builder.rs index 3ec433c39..02a23ace5 100644 --- a/crates/doc/src/builder.rs +++ b/crates/doc/src/builder.rs @@ -105,7 +105,7 @@ impl DocBuilder { .collect::>(); if sources.is_empty() { - println!("No sources detected at {}", self.sources.display()); + sh_println!("No sources detected at {}", self.sources.display())?; return Ok(()) } diff --git a/crates/doc/src/lib.rs b/crates/doc/src/lib.rs index fd8e4d3ba..174c76600 100644 --- a/crates/doc/src/lib.rs +++ b/crates/doc/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/evm/coverage/src/lib.rs b/crates/evm/coverage/src/lib.rs index 220ab6b41..7ac609123 100644 --- a/crates/evm/coverage/src/lib.rs +++ b/crates/evm/coverage/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; @@ -237,7 +240,7 @@ impl HitMap { if let (Some(len1), Some(len2)) = (len1, len2) { let len = std::cmp::max(len1.0, len2.0); let ok = hm1.bytecode.0[..*len] == hm2.bytecode.0[..*len]; - println!("consistent_bytecode: {}, {}, {}, {}", ok, len1.0, len2.0, len); + let _ = sh_println!("consistent_bytecode: {}, {}, {}, {}", ok, len1.0, len2.0, len); return ok; } true diff --git a/crates/evm/traces/src/identifier/etherscan.rs b/crates/evm/traces/src/identifier/etherscan.rs index 2af6fbb59..96e4b6966 100644 --- a/crates/evm/traces/src/identifier/etherscan.rs +++ b/crates/evm/traces/src/identifier/etherscan.rs @@ -65,7 +65,7 @@ impl EtherscanIdentifier { // filter out vyper files .filter(|(_, metadata)| !metadata.is_vyper()) .map(|(address, metadata)| async move { - println!("Compiling: {} {address}", metadata.contract_name); + sh_println!("Compiling: {} {address}", metadata.contract_name)?; let root = tempfile::tempdir()?; let root_path = root.path(); let project = etherscan_project(metadata, root_path)?; diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index dd4a89664..18136c481 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/forge/bin/cmd/install.rs b/crates/forge/bin/cmd/install.rs index 31637b90c..2024b3d23 100644 --- a/crates/forge/bin/cmd/install.rs +++ b/crates/forge/bin/cmd/install.rs @@ -97,10 +97,8 @@ impl DependencyInstallOpts { let _ = sh_println!("Missing dependencies found. Installing now...\n"); self.no_commit = true; if self.install(config, Vec::new()).is_err() { - let _ = sh_warn!( - "{}", - "Your project has missing dependencies that could not be installed." - ); + let _ = + sh_warn!("Your project has missing dependencies that could not be installed."); } true } else { diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 243ce9b22..091599305 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -908,7 +908,7 @@ fn list(runner: MultiContractRunner, filter: &ProjectPathsAwareFilter) -> Result let results = runner.list(filter); if shell::is_json() { - println!("{}", serde_json::to_string(&results)?); + sh_println!("{}", serde_json::to_string(&results)?)?; } else { for (file, contracts) in results.iter() { sh_println!("{file}")?; diff --git a/crates/script/src/execute.rs b/crates/script/src/execute.rs index 97555694a..51ab01414 100644 --- a/crates/script/src/execute.rs +++ b/crates/script/src/execute.rs @@ -255,7 +255,7 @@ For more information, please see https://eips.ethereum.org/EIPS/eip-3855", .map(|(_, chain)| *chain as u64) .format(", ") ); - sh_warn!("{}", msg)?; + sh_warn!("{msg}")?; } Ok(()) } diff --git a/crates/script/src/runner.rs b/crates/script/src/runner.rs index 51b101847..a7d950690 100644 --- a/crates/script/src/runner.rs +++ b/crates/script/src/runner.rs @@ -13,7 +13,6 @@ use foundry_evm::{ traces::{TraceKind, Traces}, }; use std::collections::VecDeque; -use yansi::Paint; /// Drives script execution #[derive(Debug)] @@ -248,7 +247,7 @@ impl ScriptRunner { Ok(DeployResult { address, raw }) => (address, raw), Err(EvmError::Execution(err)) => { let ExecutionErr { raw, reason } = *err; - println!("{}", format!("\nFailed with `{reason}`:\n").red()); + sh_err!("Failed with `{reason}`:\n")?; (Address::ZERO, raw) } Err(e) => eyre::bail!("Failed deploying contract: {e:?}"), diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index 720b970af..f8f9c9a36 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -151,8 +151,8 @@ impl PreSimulationState { .collect::>(); if self.script_config.evm_opts.verbosity > 3 { - println!("=========================="); - println!("Simulated On-chain Traces:\n"); + sh_println!("==========================")?; + sh_println!("Simulated On-chain Traces:\n")?; } let mut abort = false; @@ -163,7 +163,7 @@ impl PreSimulationState { if tx.is_none() || self.script_config.evm_opts.verbosity > 3 { for (_, trace) in &mut traces { decode_trace_arena(trace, &self.execution_artifacts.decoder).await?; - println!("{}", render_trace_arena(trace)); + sh_println!("{}", render_trace_arena(trace))?; } } diff --git a/crates/script/src/verify.rs b/crates/script/src/verify.rs index 74cc4a3f9..c013ee862 100644 --- a/crates/script/src/verify.rs +++ b/crates/script/src/verify.rs @@ -12,7 +12,6 @@ use foundry_common::ContractsByArtifact; use foundry_compilers::{info::ContractInfo, Project}; use foundry_config::{Chain, Config}; use semver::Version; -use yansi::Paint; /// State after we have broadcasted the script. /// It is assumed that at this point [BroadcastedState::sequence] contains receipts for all @@ -218,13 +217,15 @@ async fn verify_contracts( let num_verifications = future_verifications.len(); let mut num_of_successful_verifications = 0; - println!("##\nStart verification for ({num_verifications}) contracts"); + sh_println!("##\nStart verification for ({num_verifications}) contracts")?; for verification in future_verifications { match verification.await { Ok(_) => { num_of_successful_verifications += 1; } - Err(err) => eprintln!("Error during verification: {err:#}"), + Err(err) => { + sh_err!("Failed to verify contract: {err:#}")?; + } } } @@ -232,7 +233,7 @@ async fn verify_contracts( return Err(eyre!("Not all ({num_of_successful_verifications} / {num_verifications}) contracts were verified!")) } - println!("All ({num_verifications}) contracts were verified!"); + sh_println!("All ({num_verifications}) contracts were verified!")?; } Ok(()) @@ -244,15 +245,9 @@ fn check_unverified( verify: VerifyBundle, ) { if !unverifiable_contracts.is_empty() { - println!( - "\n{}", - format!( - "We haven't found any matching bytecode for the following contracts: {:?}.\n\n{}", - unverifiable_contracts, - "This may occur when resuming a verification, but the underlying source code or compiler version has changed." - ) - .yellow() - .bold(), + let _ = sh_warn!( + "We haven't found any matching bytecode for the following contracts: {:?}.\n\nThis may occur when resuming a verification, but the underlying source code or compiler version has changed.", + unverifiable_contracts ); if let Some(commit) = &sequence.commit { @@ -263,7 +258,9 @@ fn check_unverified( .unwrap_or_default(); if ¤t_commit != commit { - println!("\tScript was broadcasted on commit `{commit}`, but we are at `{current_commit}`."); + let _ = sh_warn!( + "Script was broadcasted on commit `{commit}`, but we are at `{current_commit}`." + ); } } } diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs index 0fcfb6216..9d4316b41 100644 --- a/crates/test-utils/src/lib.rs +++ b/crates/test-utils/src/lib.rs @@ -5,6 +5,9 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] +#[macro_use] +extern crate foundry_common; + #[macro_use] extern crate tracing; diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index a9ff6a7e6..7f0742143 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -177,7 +177,7 @@ fn next_url(is_ws: bool, chain: NamedChain) -> String { } #[cfg(test)] -#[allow(clippy::needless_return)] +#[allow(clippy::needless_return, clippy::disallowed_macros)] mod tests { use super::*; use alloy_primitives::address; @@ -190,7 +190,7 @@ mod tests { let mut first_abi = None; let mut failed = Vec::new(); for (i, &key) in ETHERSCAN_MAINNET_KEYS.iter().enumerate() { - eprintln!("trying key {i} ({key})"); + println!("trying key {i} ({key})"); let client = foundry_block_explorers::Client::builder() .chain(Chain::mainnet()) diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 11757978a..9603ca3a2 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -141,7 +141,7 @@ impl ExtTester { pub fn run(&self) { // Skip fork tests if the RPC url is not set. if self.fork_block.is_some() && std::env::var_os("ETH_RPC_URL").is_none() { - eprintln!("ETH_RPC_URL is not set; skipping"); + let _ = sh_eprintln!("ETH_RPC_URL is not set; skipping"); return; } @@ -159,7 +159,7 @@ impl ExtTester { if self.rev.is_empty() { let mut git = Command::new("git"); git.current_dir(root).args(["log", "-n", "1"]); - eprintln!("$ {git:?}"); + let _ = sh_println!("$ {git:?}"); let output = git.output().unwrap(); if !output.status.success() { panic!("git log failed: {output:?}"); @@ -170,7 +170,7 @@ impl ExtTester { } else { let mut git = Command::new("git"); git.current_dir(root).args(["checkout", self.rev]); - eprintln!("$ {git:?}"); + let _ = sh_println!("$ {git:?}"); let status = git.status().unwrap(); if !status.success() { panic!("git checkout failed: {status}"); @@ -181,15 +181,17 @@ impl ExtTester { for install_command in &self.install_commands { let mut install_cmd = Command::new(&install_command[0]); install_cmd.args(&install_command[1..]).current_dir(root); - eprintln!("cd {root}; {install_cmd:?}"); + let _ = sh_println!("cd {root}; {install_cmd:?}"); match install_cmd.status() { Ok(s) => { - eprintln!("\n\n{install_cmd:?}: {s}"); + let _ = sh_println!("\n\n{install_cmd:?}: {s}"); if s.success() { break; } } - Err(e) => eprintln!("\n\n{install_cmd:?}: {e}"), + Err(e) => { + let _ = sh_eprintln!("\n\n{install_cmd:?}: {e}"); + } } } @@ -223,7 +225,7 @@ impl ExtTester { /// runs each test in a separate process. Instead, we use a global lock file to ensure that only one /// test can initialize the template at a time. pub fn initialize(target: &Path) { - eprintln!("initializing {}", target.display()); + let _ = sh_println!("initializing {}", target.display()); let tpath = TEMPLATE_PATH.as_path(); pretty_err(tpath, fs::create_dir_all(tpath)); @@ -251,7 +253,7 @@ pub fn initialize(target: &Path) { if data != "1" { // Initialize and build. let (prj, mut cmd) = setup_forge("template", foundry_compilers::PathStyle::Dapptools); - eprintln!("- initializing template dir in {}", prj.root().display()); + let _ = sh_println!("- initializing template dir in {}", prj.root().display()); cmd.args(["init", "--force"]).assert_success(); // checkout forge-std @@ -281,7 +283,7 @@ pub fn initialize(target: &Path) { _read = Some(lock.read().unwrap()); } - eprintln!("- copying template dir from {}", tpath.display()); + let _ = sh_println!("- copying template dir from {}", tpath.display()); pretty_err(target, fs::create_dir_all(target)); pretty_err(target, copy_dir(tpath, target)); } @@ -291,12 +293,12 @@ pub fn clone_remote(repo_url: &str, target_dir: &str) { let mut cmd = Command::new("git"); cmd.args(["clone", "--no-tags", "--recursive", "--shallow-submodules"]); cmd.args([repo_url, target_dir]); - eprintln!("{cmd:?}"); + let _ = sh_println!("{cmd:?}"); let status = cmd.status().unwrap(); if !status.success() { panic!("git clone failed: {status}"); } - eprintln!(); + let _ = sh_println!(); } /// Setup an empty test project and return a command pointing to the forge @@ -922,7 +924,7 @@ impl TestCommand { #[track_caller] pub fn try_execute(&mut self) -> std::io::Result { - eprintln!("executing {:?}", self.cmd); + let _ = sh_println!("executing {:?}", self.cmd); let mut child = self.cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::piped()).spawn()?; if let Some(fun) = self.stdin_fun.take() { diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index a4f368a96..a8fc1ace7 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -22,7 +22,6 @@ use foundry_config::{figment, impl_figment_convert, Config}; use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, utils::configure_tx_env}; use revm_primitives::AccountInfo; use std::path::PathBuf; -use yansi::Paint; impl_figment_convert!(VerifyBytecodeArgs); @@ -142,11 +141,11 @@ impl VerifyBytecodeArgs { } if !shell::is_json() { - println!( + sh_println!( "Verifying bytecode for contract {} at address {}", - self.contract.name.clone().green(), - self.address.green() - ); + self.contract.name, + self.address + )?; } let mut json_results: Vec = vec![]; @@ -212,12 +211,10 @@ impl VerifyBytecodeArgs { if maybe_predeploy { if !shell::is_json() { - println!( - "{}", - format!("Attempting to verify predeployed contract at {:?}. Ignoring creation code verification.", self.address) - .yellow() - .bold() - ) + sh_warn!( + "Attempting to verify predeployed contract at {:?}. Ignoring creation code verification.", + self.address + )?; } // Append constructor args to the local_bytecode. diff --git a/crates/verify/src/etherscan/mod.rs b/crates/verify/src/etherscan/mod.rs index 9b5b1fa34..ae1443962 100644 --- a/crates/verify/src/etherscan/mod.rs +++ b/crates/verify/src/etherscan/mod.rs @@ -65,11 +65,11 @@ impl VerificationProvider for EtherscanVerificationProvider { if !args.skip_is_verified_check && self.is_contract_verified(ðerscan, &verify_args).await? { - println!( + sh_println!( "\nContract [{}] {:?} is already verified. Skipping verification.", verify_args.contract_name, verify_args.address.to_checksum(None) - ); + )?; return Ok(()) } @@ -79,10 +79,11 @@ impl VerificationProvider for EtherscanVerificationProvider { let retry: Retry = args.retry.into(); let resp = retry .run_async(|| async { - println!( + sh_println!( "\nSubmitting verification for [{}] {}.", - verify_args.contract_name, verify_args.address - ); + verify_args.contract_name, + verify_args.address + )?; let resp = etherscan .submit_contract_verification(&verify_args) .await @@ -109,10 +110,12 @@ impl VerificationProvider for EtherscanVerificationProvider { } warn!("Failed verify submission: {:?}", resp); - eprintln!( - "Encountered an error verifying this contract:\nResponse: `{}`\nDetails: `{}`", - resp.message, resp.result - ); + sh_err!( + "Encountered an error verifying this contract:\nResponse: `{}`\nDetails: + `{}`", + resp.message, + resp.result + )?; std::process::exit(1); } @@ -121,12 +124,12 @@ impl VerificationProvider for EtherscanVerificationProvider { .await?; if let Some(resp) = resp { - println!( + sh_println!( "Submitted contract for verification:\n\tResponse: `{}`\n\tGUID: `{}`\n\tURL: {}", resp.message, resp.result, etherscan.address_url(args.address) - ); + )?; if args.watch { let check_args = VerifyCheckArgs { @@ -139,7 +142,7 @@ impl VerificationProvider for EtherscanVerificationProvider { return self.check(check_args).await } } else { - println!("Contract source code already verified"); + sh_println!("Contract source code already verified")?; } Ok(()) @@ -166,9 +169,10 @@ impl VerificationProvider for EtherscanVerificationProvider { trace!(?resp, "Received verification response"); - eprintln!( + let _ = sh_println!( "Contract verification status:\nResponse: `{}`\nDetails: `{}`", - resp.message, resp.result + resp.message, + resp.result ); if resp.result == "Pending in queue" { @@ -180,7 +184,7 @@ impl VerificationProvider for EtherscanVerificationProvider { } if resp.result == "Already Verified" { - println!("Contract source code already verified"); + let _ = sh_println!("Contract source code already verified"); return Ok(()) } @@ -189,7 +193,7 @@ impl VerificationProvider for EtherscanVerificationProvider { } if resp.result == "Pass - Verified" { - println!("Contract successfully verified"); + let _ = sh_println!("Contract successfully verified"); } Ok(()) diff --git a/crates/verify/src/sourcify.rs b/crates/verify/src/sourcify.rs index 9dbe027ef..b215fd1af 100644 --- a/crates/verify/src/sourcify.rs +++ b/crates/verify/src/sourcify.rs @@ -40,11 +40,11 @@ impl VerificationProvider for SourcifyVerificationProvider { let resp = retry .run_async(|| { async { - println!( + sh_println!( "\nSubmitting verification for [{}] {:?}.", context.target_name, args.address.to_string() - ); + )?; let response = client .post(args.verifier.verifier_url.as_deref().unwrap_or(SOURCIFY_URL)) .header("Content-Type", "application/json") @@ -145,15 +145,15 @@ impl SourcifyVerificationProvider { match response.status.as_str() { "perfect" => { if let Some(ts) = &response.storage_timestamp { - println!("Contract source code already verified. Storage Timestamp: {ts}"); + sh_println!("Contract source code already verified. Storage Timestamp: {ts}")?; } else { - println!("Contract successfully verified"); + sh_println!("Contract successfully verified")?; } } "partial" => { - println!("The recompiled contract partially matches the deployed version"); + sh_println!("The recompiled contract partially matches the deployed version")?; } - "false" => println!("Contract source code is not verified"), + "false" => sh_println!("Contract source code is not verified")?, s => eyre::bail!("Unknown status from sourcify. Status: {s:?}"), } Ok(()) diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index e3065aca0..19c63e7fb 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -145,7 +145,7 @@ pub fn print_result( ) { if let Some(res) = res { if !shell::is_json() { - println!( + let _ = sh_println!( "{} with status {}", format!("{bytecode_type:?} code matched").green().bold(), res.green().bold() @@ -155,17 +155,12 @@ pub fn print_result( json_results.push(json_res); } } else if !shell::is_json() { - println!( - "{}", - format!( - "{bytecode_type:?} code did not match - this may be due to varying compiler settings" - ) - .red() - .bold() + let _ = sh_err!( + "{bytecode_type:?} code did not match - this may be due to varying compiler settings" ); let mismatches = find_mismatch_in_settings(etherscan_config, config); for mismatch in mismatches { - println!("{}", mismatch.red().bold()); + let _ = sh_eprintln!("{}", mismatch.red().bold()); } } else { let json_res = JsonResult { diff --git a/crates/verify/src/verify.rs b/crates/verify/src/verify.rs index 4a3abaa36..5f3e55329 100644 --- a/crates/verify/src/verify.rs +++ b/crates/verify/src/verify.rs @@ -197,12 +197,12 @@ impl VerifyArgs { let args = EtherscanVerificationProvider::default() .create_verify_request(&self, &context) .await?; - println!("{}", args.source); + sh_println!("{}", args.source)?; return Ok(()) } let verifier_url = self.verifier.verifier_url.clone(); - println!("Start verifying contract `{}` deployed on {chain}", self.address); + sh_println!("Start verifying contract `{}` deployed on {chain}", self.address)?; self.verifier.verifier.client(&self.etherscan.key())?.verify(self, context).await.map_err(|err| { if let Some(verifier_url) = verifier_url { match Url::parse(&verifier_url) { @@ -333,7 +333,10 @@ impl_figment_convert_cast!(VerifyCheckArgs); impl VerifyCheckArgs { /// Run the verify command to submit the contract's source code for verification on etherscan pub async fn run(self) -> Result<()> { - println!("Checking verification status on {}", self.etherscan.chain.unwrap_or_default()); + sh_println!( + "Checking verification status on {}", + self.etherscan.chain.unwrap_or_default() + )?; self.verifier.verifier.client(&self.etherscan.key())?.check(self).await } } From 896794a21aef9326b3350ae243fb6d91ea945d65 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Sat, 9 Nov 2024 19:04:49 +0200 Subject: [PATCH 11/58] chore: typo anvil_getIntervalMing -> anvil_getIntervalMining (#9292) chore: typo anvil_getIntervalMining --- crates/anvil/core/src/eth/mod.rs | 5 ++++- crates/anvil/src/eth/api.rs | 6 +++--- crates/anvil/tests/it/anvil.rs | 6 +++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index 38691ba0d..33ffda6a7 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -395,7 +395,10 @@ pub enum EthRequest { SetIntervalMining(u64), /// Gets the current mining behavior - #[cfg_attr(feature = "serde", serde(rename = "anvil_getIntervalMing", with = "empty_params"))] + #[cfg_attr( + feature = "serde", + serde(rename = "anvil_getIntervalMining", with = "empty_params") + )] GetIntervalMining(()), /// Removes transactions from the pool diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index e5210b0c2..6ee7c6d60 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -326,7 +326,7 @@ impl EthApi { EthRequest::SetIntervalMining(interval) => { self.anvil_set_interval_mining(interval).to_rpc_result() } - EthRequest::GetIntervalMining(()) => self.anvil_get_interval_ming().to_rpc_result(), + EthRequest::GetIntervalMining(()) => self.anvil_get_interval_mining().to_rpc_result(), EthRequest::DropTransaction(tx) => { self.anvil_drop_transaction(tx).await.to_rpc_result() } @@ -1668,8 +1668,8 @@ impl EthApi { /// Returns the value of mining interval, if set. /// - /// Handler for ETH RPC call: `anvil_getIntervalMing` - pub fn anvil_get_interval_ming(&self) -> Result> { + /// Handler for ETH RPC call: `anvil_getIntervalMining`. + pub fn anvil_get_interval_mining(&self) -> Result> { node_info!("anvil_getIntervalMining"); Ok(self.miner.get_interval()) } diff --git a/crates/anvil/tests/it/anvil.rs b/crates/anvil/tests/it/anvil.rs index 17b94f041..65eeac70b 100644 --- a/crates/anvil/tests/it/anvil.rs +++ b/crates/anvil/tests/it/anvil.rs @@ -12,14 +12,14 @@ async fn test_can_change_mining_mode() { let provider = handle.http_provider(); assert!(api.anvil_get_auto_mine().unwrap()); - assert!(api.anvil_get_interval_ming().unwrap().is_none()); + assert!(api.anvil_get_interval_mining().unwrap().is_none()); let num = provider.get_block_number().await.unwrap(); assert_eq!(num, 0); api.anvil_set_interval_mining(1).unwrap(); assert!(!api.anvil_get_auto_mine().unwrap()); - assert!(matches!(api.anvil_get_interval_ming().unwrap(), Some(1))); + assert!(matches!(api.anvil_get_interval_mining().unwrap(), Some(1))); // changing the mining mode will instantly mine a new block tokio::time::sleep(std::time::Duration::from_millis(500)).await; let num = provider.get_block_number().await.unwrap(); @@ -32,7 +32,7 @@ async fn test_can_change_mining_mode() { // assert that no block is mined when the interval is set to 0 api.anvil_set_interval_mining(0).unwrap(); assert!(!api.anvil_get_auto_mine().unwrap()); - assert!(api.anvil_get_interval_ming().unwrap().is_none()); + assert!(api.anvil_get_interval_mining().unwrap().is_none()); tokio::time::sleep(std::time::Duration::from_millis(1000)).await; let num = provider.get_block_number().await.unwrap(); assert_eq!(num, 1); From 765969d1612aa63283859f69d616983113b2c484 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 10 Nov 2024 02:53:07 +0000 Subject: [PATCH 12/58] chore(deps): weekly `cargo update` (#9293) Locking 61 packages to latest compatible versions Updating allocator-api2 v0.2.18 -> v0.2.19 Updating alloy-chains v0.1.46 -> v0.1.47 Updating anyhow v1.0.92 -> v1.0.93 Updating arbitrary v1.3.2 -> v1.4.1 Updating aws-config v1.5.9 -> v1.5.10 Updating aws-sdk-kms v1.49.0 -> v1.50.0 Updating aws-sdk-sso v1.48.0 -> v1.49.0 Updating aws-sdk-ssooidc v1.49.0 -> v1.50.0 Updating aws-sdk-sts v1.48.0 -> v1.49.0 Updating aws-smithy-runtime-api v1.7.2 -> v1.7.3 Updating aws-smithy-types v1.2.8 -> v1.2.9 Updating cc v1.1.36 -> v1.1.37 Updating clap_complete v4.5.36 -> v4.5.37 Updating derive_arbitrary v1.3.2 -> v1.4.1 Updating fastrand v2.1.1 -> v2.2.0 Downgrading fs4 v0.10.0 -> v0.9.1 Updating gcloud-sdk v0.25.7 -> v0.25.8 Updating handlebars v5.1.2 -> v6.2.0 Updating hyper-timeout v0.5.1 -> v0.5.2 Adding icu_collections v1.5.0 Adding icu_locid v1.5.0 Adding icu_locid_transform v1.5.0 Adding icu_locid_transform_data v1.5.0 Adding icu_normalizer v1.5.0 Adding icu_normalizer_data v1.5.0 Adding icu_properties v1.5.1 Adding icu_properties_data v1.5.0 Adding icu_provider v1.5.0 Adding icu_provider_macros v1.5.0 Updating idna v0.5.0 -> v1.0.3 Adding idna_adapter v1.2.0 Updating libc v0.2.161 -> v0.2.162 Adding litemap v0.7.3 Updating mdbook v0.4.40 -> v0.4.42 Updating newtype-uuid v1.1.2 -> v1.1.3 Adding num-modular v0.6.1 Adding num-order v1.2.0 Updating quinn-udp v0.5.6 -> v0.5.7 Updating security-framework-sys v2.12.0 -> v2.12.1 Updating serial_test v3.1.1 -> v3.2.0 Updating serial_test_derive v3.1.1 -> v3.2.0 Updating snapbox v0.6.19 -> v0.6.20 Adding stable_deref_trait v1.2.0 Downgrading svm-rs v0.5.8 -> v0.5.7 (available: v0.5.8) Downgrading svm-rs-builds v0.5.8 -> v0.5.7 (available: v0.5.8) Adding synstructure v0.13.1 Updating tempfile v3.13.0 -> v3.14.0 Adding tinystr v0.7.6 Updating tokio v1.41.0 -> v1.41.1 Updating tracy-client-sys v0.24.1 -> v0.24.2 Removing unicode-bidi v0.3.17 Updating url v2.5.2 -> v2.5.3 Adding utf16_iter v1.0.5 Adding utf8_iter v1.0.4 Adding write16 v1.0.0 Adding writeable v0.5.5 Adding yoke v0.7.4 Adding yoke-derive v0.7.4 Adding zerofrom v0.1.4 Adding zerofrom-derive v0.1.4 Adding zerovec v0.10.4 Adding zerovec-derive v0.10.3 note: pass `--verbose` to see 42 unchanged dependencies behind latest Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> --- Cargo.lock | 416 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 340 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a58b40977..b18148fe9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,15 +68,15 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "611cc2ae7d2e242c457e4be7f97036b8ad9ca152b499f53faf99b1ed8fc2553f" [[package]] name = "alloy-chains" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836cf02383d9ebb35502d379bcd1ae803155094077eaab9c29131d888cd5fa3e" +checksum = "18c5c520273946ecf715c0010b4e3503d7eba9893cd9ce6b7fff5654c4a3c470" dependencies = [ "alloy-primitives", "num_enum", @@ -972,15 +972,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ "derive_arbitrary", ] @@ -1261,9 +1261,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-config" -version = "1.5.9" +version = "1.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6448cfb224dd6a9b9ac734f58622dd0d4751f3589f3b777345745f46b2eb14" +checksum = "9b49afaa341e8dd8577e1a2200468f98956d6eda50bcf4a53246cc00174ba924" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1328,9 +1328,9 @@ dependencies = [ [[package]] name = "aws-sdk-kms" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4c89f1d2e0df99ccd21f98598c1e587ad78bd87ae22a74aba392b5566bb038" +checksum = "bfd059dacda4dfd5b57f2bd453fc6555f9acb496cb77508d517da24cf5d73167" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1350,9 +1350,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded855583fa1d22e88fe39fd6062b062376e50a8211989e07cf5e38d52eb3453" +checksum = "09677244a9da92172c8dc60109b4a9658597d4d298b188dd0018b6a66b410ca4" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1372,9 +1372,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9177ea1192e6601ae16c7273385690d88a7ed386a00b74a6bc894d12103cd933" +checksum = "81fea2f3a8bb3bd10932ae7ad59cc59f65f270fc9183a7e91f501dc5efbef7ee" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1394,9 +1394,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823ef553cf36713c97453e2ddff1eb8f62be7f4523544e2a5db64caf80100f0a" +checksum = "53dcf5e7d9bd1517b8b998e170e650047cea8a2b85fe1835abe3210713e541b7" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1517,9 +1517,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime-api" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e086682a53d3aa241192aa110fa8dfce98f2f5ac2ead0de84d41582c7e8fdb96" +checksum = "92165296a47a812b267b4f41032ff8069ab7ff783696d217f0994a0d7ab585cd" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -1534,9 +1534,9 @@ dependencies = [ [[package]] name = "aws-smithy-types" -version = "1.2.8" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c9cdc179e6afbf5d391ab08c85eac817b51c87e1892a5edb5f7bbdc64314b4" +checksum = "4fbd94a32b3a7d55d3806fe27d98d3ad393050439dd05eb53ece36ec5e3d3510" dependencies = [ "base64-simd", "bytes", @@ -1998,9 +1998,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.36" +version = "1.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70" +checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" dependencies = [ "shlex", ] @@ -2137,9 +2137,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.36" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2" +checksum = "11611dca53440593f38e6b25ec629de50b14cdfa63adc0fb856115a2c6d97595" dependencies = [ "clap", ] @@ -2659,9 +2659,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", @@ -3196,9 +3196,9 @@ checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" [[package]] name = "fastrand" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" [[package]] name = "fastrlp" @@ -4168,9 +4168,9 @@ checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" [[package]] name = "fs4" -version = "0.10.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec6fcfb3c0c1d71612528825042261419d5dade9678c39a781e05b63677d9b32" +checksum = "e8c6b3bd49c37d2aa3f3f2220233b29a7cd23f79d1fe70e5337d25fb390793de" dependencies = [ "rustix", "windows-sys 0.52.0", @@ -4304,9 +4304,9 @@ checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" [[package]] name = "gcloud-sdk" -version = "0.25.7" +version = "0.25.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a1130d4e37435a63bd9d968a33c11b64bf35a2013779a353e29cd3598989d39" +checksum = "0775bfa745cdf7287ae9765a685a813b91049b6b6d5ca3de20a3d5d16a80d8b2" dependencies = [ "async-trait", "bytes", @@ -4676,11 +4676,12 @@ dependencies = [ [[package]] name = "handlebars" -version = "5.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08485b96a0e6393e9e4d1b8d48cf74ad6c063cd905eb33f42c1ce3f0377539b" +checksum = "fd4ccde012831f9a071a637b0d4e31df31c0f6c525784b35ae76a9ac6bc1e315" dependencies = [ "log", + "num-order", "pest", "pest_derive", "serde", @@ -4967,9 +4968,9 @@ dependencies = [ [[package]] name = "hyper-timeout" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ "hyper 1.5.0", "hyper-util", @@ -5036,6 +5037,124 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -5044,12 +5163,23 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", ] [[package]] @@ -5462,9 +5592,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.161" +version = "0.2.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" [[package]] name = "libdbus-sys" @@ -5511,6 +5641,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -5608,9 +5744,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.40" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45a38e19bd200220ef07c892b0157ad3d2365e5b5a267ca01ad12182491eea5" +checksum = "7624879735513024d323e7267a0b3a7176aceb0db537939beb4ee31d9e8945e3" dependencies = [ "ammonia", "anyhow", @@ -5808,9 +5944,9 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "newtype-uuid" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4933943834e236c864a48aefdc2da43885dbd5eb77bff3ab20f31e0c3146f5" +checksum = "4c8781e2ef64806278a55ad223f0bc875772fd40e1fe6e73e8adbf027817229d" dependencies = [ "uuid 1.11.0", ] @@ -5990,6 +6126,21 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", +] + [[package]] name = "num-rational" version = "0.4.2" @@ -6953,9 +7104,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e346e016eacfff12233c243718197ca12f148c84e1e84268a896699b41c71780" +checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" dependencies = [ "cfg_aliases 0.2.1", "libc", @@ -7810,9 +7961,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" dependencies = [ "core-foundation-sys", "libc", @@ -7949,9 +8100,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b4b487fe2acf240a021cf57c6b2b4903b1e78ca0ecd862a71b71d2a51fed77d" +checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" dependencies = [ "futures", "log", @@ -7963,9 +8114,9 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.1.1" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" +checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", @@ -8148,9 +8299,9 @@ checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" [[package]] name = "snapbox" -version = "0.6.19" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881f1849454828a68363dd288b7a0a071e55e2a4356d2c38b567db18a9be0d9f" +checksum = "1373ce406dfad473059bbc31d807715642182bbc952a811952b58d1c9e41dcfa" dependencies = [ "anstream", "anstyle", @@ -8260,6 +8411,12 @@ dependencies = [ "der", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -8356,9 +8513,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "svm-rs" -version = "0.5.8" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "040017ebc08d781c457a3bfe9c5c2a99f902f8133eb91ef82b7876b053962ece" +checksum = "4aebac1b1ef2b46e2e2bdf3c09db304800f2a77c1fa902bd5231490203042be8" dependencies = [ "const-hex", "dirs 5.0.1", @@ -8376,9 +8533,9 @@ dependencies = [ [[package]] name = "svm-rs-builds" -version = "0.5.8" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a76fff24884135e66485c726e46b90d7ced3118786b244d05df9ea8aeac8b1b" +checksum = "f2fa0f145894cb4d1c14446f08098ee5f21fc37ccbd1a7dd9dd355bbc806de3b" dependencies = [ "build_const", "const-hex", @@ -8436,6 +8593,17 @@ dependencies = [ "futures-core", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "tap" version = "1.0.1" @@ -8444,9 +8612,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -8618,6 +8786,16 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + [[package]] name = "tinyvec" version = "1.8.0" @@ -8635,9 +8813,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.41.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" dependencies = [ "backtrace", "bytes", @@ -9010,11 +9188,12 @@ dependencies = [ [[package]] name = "tracy-client-sys" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68613466112302fdbeabc5fa55f7d57462a0b247d5a6b7d7e09401fb471a144d" +checksum = "3637e734239e12ab152cd269302500bd063f37624ee210cd04b4936ed671f3b1" dependencies = [ "cc", + "windows-targets 0.52.6", ] [[package]] @@ -9102,12 +9281,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" -[[package]] -name = "unicode-bidi" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" - [[package]] name = "unicode-bom" version = "2.0.3" @@ -9178,9 +9351,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.2" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -9199,6 +9372,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.2" @@ -9840,6 +10025,18 @@ version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "ws_stream_wasm" version = "0.7.4" @@ -9883,6 +10080,30 @@ dependencies = [ "is-terminal", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -9904,6 +10125,27 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -9924,6 +10166,28 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "zip" version = "2.2.0" From e028b92698eae7e5019025e1784e7c06c3cae534 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Sun, 10 Nov 2024 13:19:11 +0200 Subject: [PATCH 13/58] fix(trace): check fn sigs for contract with fallbacks (#9287) * fix(trace): check fn sigs for contract with fallbacks * Add Json test * Execute test with traces * Simplify, check only for decoded function --- crates/evm/traces/src/decoder/mod.rs | 23 ++++- crates/forge/tests/cli/cmd.rs | 144 +++++++++++++++++++++++++++ 2 files changed, 166 insertions(+), 1 deletion(-) diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 43a53286c..b63c7f1d7 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -121,6 +121,8 @@ pub struct CallTraceDecoder { pub labels: HashMap, /// Contract addresses that have a receive function. pub receive_contracts: Vec
, + /// Contract addresses that have fallback functions, mapped to function sigs. + pub fallback_contracts: HashMap>, /// All known functions. pub functions: HashMap>, @@ -188,6 +190,7 @@ impl CallTraceDecoder { (POINT_EVALUATION, "PointEvaluation".to_string()), ]), receive_contracts: Default::default(), + fallback_contracts: Default::default(), functions: hh_funcs() .chain( @@ -222,6 +225,7 @@ impl CallTraceDecoder { } self.receive_contracts.clear(); + self.fallback_contracts.clear(); } /// Identify unknown addresses in the specified call trace using the specified identifier. @@ -317,6 +321,14 @@ impl CallTraceDecoder { if abi.receive.is_some() { self.receive_contracts.push(*address); } + + if abi.fallback.is_some() { + let mut functions_sig = vec![]; + for function in abi.functions() { + functions_sig.push(function.signature()); + } + self.fallback_contracts.insert(*address, functions_sig); + } } } @@ -379,9 +391,18 @@ impl CallTraceDecoder { }; }; + // If traced contract is a fallback contract, check if it has the decoded function. + // If not, then replace call data signature with `fallback`. + let mut call_data = self.decode_function_input(trace, func); + if let Some(fallback_functions) = self.fallback_contracts.get(&trace.address) { + if !fallback_functions.contains(&func.signature()) { + call_data.signature = "fallback()".into(); + } + } + DecodedCallTrace { label, - call_data: Some(self.decode_function_input(trace, func)), + call_data: Some(call_data), return_data: self.decode_function_output(trace, functions), } } else { diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index feb608a1e..89335a492 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -2390,6 +2390,150 @@ contract CounterTest is DSTest { ); }); +// +forgetest_init!(gas_report_with_fallback, |prj, cmd| { + prj.add_test( + "DelegateProxyTest.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract ProxiedContract { + uint256 public amount; + + function deposit(uint256 aba) external { + amount = amount * 2; + } + + function deposit() external { + } +} + +contract DelegateProxy { + address internal implementation; + + constructor(address counter) { + implementation = counter; + } + + function deposit() external { + } + + fallback() external payable { + address addr = implementation; + + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), addr, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } +} + +contract GasReportFallbackTest is Test { + function test_fallback_gas_report() public { + ProxiedContract proxied = ProxiedContract(address(new DelegateProxy(address(new ProxiedContract())))); + proxied.deposit(100); + proxied.deposit(); + } +} +"#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_fallback_gas_report", "-vvvv", "--gas-report"]) + .assert_success() + .stdout_eq(str![[r#" +... +Ran 1 test for test/DelegateProxyTest.sol:GasReportFallbackTest +[PASS] test_fallback_gas_report() ([GAS]) +Traces: + [331067] GasReportFallbackTest::test_fallback_gas_report() + ├─ [106511] → new ProxiedContract@[..] + │ └─ ← [Return] 246 bytes of code + ├─ [108698] → new DelegateProxy@[..] + │ └─ ← [Return] 143 bytes of code + ├─ [29396] DelegateProxy::fallback(100) + │ ├─ [3320] ProxiedContract::deposit(100) [delegatecall] + │ │ └─ ← [Stop] + │ └─ ← [Return] + ├─ [21160] DelegateProxy::deposit() + │ └─ ← [Stop] + └─ ← [Stop] + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] +| test/DelegateProxyTest.sol:DelegateProxy contract | | | | | | +|---------------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 108698 | 315 | | | | | +| Function Name | min | avg | median | max | # calls | +| deposit | 21160 | 21160 | 21160 | 21160 | 1 | +| fallback | 29396 | 29396 | 29396 | 29396 | 1 | + + +| test/DelegateProxyTest.sol:ProxiedContract contract | | | | | | +|-----------------------------------------------------|-----------------|------|--------|------|---------| +| Deployment Cost | Deployment Size | | | | | +| 106511 | 276 | | | | | +| Function Name | min | avg | median | max | # calls | +| deposit | 3320 | 3320 | 3320 | 3320 | 1 | +... + +"#]]); + + cmd.forge_fuse() + .args(["test", "--mt", "test_fallback_gas_report", "--gas-report", "--json"]) + .assert_success() + .stdout_eq( + str![[r#" +[ + { + "contract": "test/DelegateProxyTest.sol:DelegateProxy", + "deployment": { + "gas": 108698, + "size": 315 + }, + "functions": { + "deposit()": { + "calls": 1, + "min": 21160, + "mean": 21160, + "median": 21160, + "max": 21160 + }, + "fallback()": { + "calls": 1, + "min": 29396, + "mean": 29396, + "median": 29396, + "max": 29396 + } + } + }, + { + "contract": "test/DelegateProxyTest.sol:ProxiedContract", + "deployment": { + "gas": 106511, + "size": 276 + }, + "functions": { + "deposit(uint256)": { + "calls": 1, + "min": 3320, + "mean": 3320, + "median": 3320, + "max": 3320 + } + } + } +] +"#]] + .is_json(), + ); +}); + forgetest_init!(can_use_absolute_imports, |prj, cmd| { let remapping = prj.paths().libraries[0].join("myDependency"); let config = Config { From b7fe62ef1f58bfa2fe1980cc0f065dfc48b31d30 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Mon, 11 Nov 2024 11:27:19 +0100 Subject: [PATCH 14/58] fix: use regular `println` in internal test utils to avoid interfering with `cargo test` runner (#9296) * use regular println to avoid interfering with cargo test runner * revert test change --- crates/script/src/receipts.rs | 2 +- crates/test-utils/src/util.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/script/src/receipts.rs b/crates/script/src/receipts.rs index af80734c5..c11fdd71a 100644 --- a/crates/script/src/receipts.rs +++ b/crates/script/src/receipts.rs @@ -72,7 +72,7 @@ pub fn format_receipt(chain: Chain, receipt: &AnyTransactionReceipt) -> String { let gas_used = receipt.gas_used; let gas_price = receipt.effective_gas_price; format!( - "\n##### {chain}\n{status}Hash: {tx_hash:?}{caddr}\nBlock: {bn}\n{gas}\n\n", + "\n##### {chain}\n{status} Hash: {tx_hash:?}{caddr}\nBlock: {bn}\n{gas}\n\n", status = if !receipt.inner.inner.inner.receipt.status.coerce_status() { "❌ [Failed]" } else { diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 9603ca3a2..5d242800f 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -224,8 +224,9 @@ impl ExtTester { /// This used to use a `static` `Lazy`, but this approach does not with `cargo-nextest` because it /// runs each test in a separate process. Instead, we use a global lock file to ensure that only one /// test can initialize the template at a time. +#[allow(clippy::disallowed_macros)] pub fn initialize(target: &Path) { - let _ = sh_println!("initializing {}", target.display()); + println!("initializing {}", target.display()); let tpath = TEMPLATE_PATH.as_path(); pretty_err(tpath, fs::create_dir_all(tpath)); @@ -253,7 +254,7 @@ pub fn initialize(target: &Path) { if data != "1" { // Initialize and build. let (prj, mut cmd) = setup_forge("template", foundry_compilers::PathStyle::Dapptools); - let _ = sh_println!("- initializing template dir in {}", prj.root().display()); + println!("- initializing template dir in {}", prj.root().display()); cmd.args(["init", "--force"]).assert_success(); // checkout forge-std @@ -283,7 +284,7 @@ pub fn initialize(target: &Path) { _read = Some(lock.read().unwrap()); } - let _ = sh_println!("- copying template dir from {}", tpath.display()); + println!("- copying template dir from {}", tpath.display()); pretty_err(target, fs::create_dir_all(target)); pretty_err(target, copy_dir(tpath, target)); } From 8c01706c96e457bac6a4d60be9c27ccbceca6396 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:25:42 +0200 Subject: [PATCH 15/58] feat(`cast run`): add `--etherscan-api-key` to resolve contract names (#9295) * fix(cast run): decode traces for non mainnet * Add test * Changes after review: use EtherscanOpts, remove short -e from evm_version Simplify test to avoid rate limiting. --- crates/cast/bin/cmd/run.rs | 11 +++++++++-- crates/cast/tests/cli/main.rs | 29 +++++++++++++++++++++++++++-- crates/evm/core/src/opts.rs | 12 ++++++++---- crates/test-utils/src/rpc.rs | 16 +++++++++++++++- 4 files changed, 59 insertions(+), 9 deletions(-) diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 11c7b507e..7389d1f35 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -5,7 +5,7 @@ use cast::revm::primitives::EnvWithHandlerCfg; use clap::Parser; use eyre::{Result, WrapErr}; use foundry_cli::{ - opts::RpcOpts, + opts::{EtherscanOpts, RpcOpts}, utils::{handle_traces, init_progress, TraceResult}, }; use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; @@ -58,13 +58,16 @@ pub struct RunArgs { #[arg(long, short)] label: Vec, + #[command(flatten)] + etherscan: EtherscanOpts, + #[command(flatten)] rpc: RpcOpts, /// The EVM version to use. /// /// Overrides the version specified in the config. - #[arg(long, short)] + #[arg(long)] evm_version: Option, /// Sets the number of assumed available compute units per second for this provider @@ -269,6 +272,10 @@ impl figment::Provider for RunArgs { map.insert("alphanet".into(), self.alphanet.into()); } + if let Some(api_key) = &self.etherscan.key { + map.insert("etherscan_api_key".into(), api_key.as_str().into()); + } + if let Some(evm_version) = self.evm_version { map.insert("evm_version".into(), figment::value::Value::serialize(evm_version)?); } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 6fb3ddb73..29527f7dc 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -6,8 +6,8 @@ use anvil::{EthereumHardfork, NodeConfig}; use foundry_test_utils::{ casttest, file, rpc::{ - next_http_rpc_endpoint, next_mainnet_etherscan_api_key, next_rpc_endpoint, - next_ws_rpc_endpoint, + next_etherscan_api_key, next_http_rpc_endpoint, next_mainnet_etherscan_api_key, + next_rpc_endpoint, next_ws_rpc_endpoint, }, str, util::OutputExt, @@ -1503,3 +1503,28 @@ casttest!(fetch_constructor_args_from_etherscan, |_prj, cmd| { "#]]); }); + +// +casttest!(test_non_mainnet_traces, |prj, cmd| { + prj.clear(); + cmd.args([ + "run", + "0xa003e419e2d7502269eb5eda56947b580120e00abfd5b5460d08f8af44a0c24f", + "--rpc-url", + next_rpc_endpoint(NamedChain::Optimism).as_str(), + "--etherscan-api-key", + next_etherscan_api_key(NamedChain::Optimism).as_str(), + ]) + .assert_success() + .stdout_eq(str![[r#" +Executing previous transactions from the block. +Traces: + [33841] FiatTokenProxy::fallback(0x111111125421cA6dc452d289314280a0f8842A65, 164054805 [1.64e8]) + ├─ [26673] FiatTokenV2_2::approve(0x111111125421cA6dc452d289314280a0f8842A65, 164054805 [1.64e8]) [delegatecall] + │ ├─ emit Approval(owner: 0x9a95Af47C51562acfb2107F44d7967DF253197df, spender: 0x111111125421cA6dc452d289314280a0f8842A65, value: 164054805 [1.64e8]) + │ └─ ← [Return] true + └─ ← [Return] true +... + +"#]]); +}); diff --git a/crates/evm/core/src/opts.rs b/crates/evm/core/src/opts.rs index 7a41d0756..17ecbcca1 100644 --- a/crates/evm/core/src/opts.rs +++ b/crates/evm/core/src/opts.rs @@ -192,10 +192,6 @@ impl EvmOpts { /// Returns the chain ID from the RPC, if any. pub async fn get_remote_chain_id(&self) -> Option { if let Some(ref url) = self.fork_url { - if url.contains("mainnet") { - trace!(?url, "auto detected mainnet chain"); - return Some(Chain::mainnet()); - } trace!(?url, "retrieving chain via eth_chainId"); let provider = ProviderBuilder::new(url.as_str()) .compute_units_per_second(self.get_compute_units_per_second()) @@ -206,6 +202,14 @@ impl EvmOpts { if let Ok(id) = provider.get_chain_id().await { return Some(Chain::from(id)); } + + // Provider URLs could be of the format `{CHAIN_IDENTIFIER}-mainnet` + // (e.g. Alchemy `opt-mainnet`, `arb-mainnet`), fallback to this method only + // if we're not able to retrieve chain id from `RetryProvider`. + if url.contains("mainnet") { + trace!(?url, "auto detected mainnet chain"); + return Some(Chain::mainnet()); + } } None diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index 7f0742143..a974e3954 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -1,6 +1,6 @@ //! RPC API keys utilities. -use foundry_config::NamedChain; +use foundry_config::{NamedChain, NamedChain::Optimism}; use rand::seq::SliceRandom; use std::sync::{ atomic::{AtomicUsize, Ordering}, @@ -75,6 +75,10 @@ static ETHERSCAN_MAINNET_KEYS: LazyLock> = LazyLock::new(|| { keys }); +// List of etherscan keys for Optimism. +static ETHERSCAN_OPTIMISM_KEYS: LazyLock> = + LazyLock::new(|| vec!["JQNGFHINKS1W7Y5FRXU4SPBYF43J3NYK46"]); + /// Returns the next index to use. fn next() -> usize { static NEXT_INDEX: AtomicUsize = AtomicUsize::new(0); @@ -127,6 +131,16 @@ pub fn next_mainnet_etherscan_api_key() -> String { ETHERSCAN_MAINNET_KEYS[idx].to_string() } +/// Returns the next etherscan api key for given chain. +pub fn next_etherscan_api_key(chain: NamedChain) -> String { + let keys = match chain { + Optimism => ÐERSCAN_OPTIMISM_KEYS, + _ => ÐERSCAN_MAINNET_KEYS, + }; + let idx = next() % keys.len(); + keys[idx].to_string() +} + fn next_url(is_ws: bool, chain: NamedChain) -> String { use NamedChain::*; From f8d92341baa030675db135d08a574f4caeb96177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Urbanek?= Date: Mon, 11 Nov 2024 16:56:53 +0100 Subject: [PATCH 16/58] feat(cast): add artifact method (#9249) * feat(cast): add artifact method * Remove unneeded clone * Get chain info from provider * Rebase fix --- crates/cast/bin/args.rs | 6 +- crates/cast/bin/cmd/artifact.rs | 95 +++++++++++++++++++++++++ crates/cast/bin/cmd/constructor_args.rs | 11 +-- crates/cast/bin/cmd/creation_code.rs | 28 +++++--- crates/cast/bin/cmd/mod.rs | 1 + crates/cast/bin/main.rs | 1 + crates/cast/tests/cli/main.rs | 23 ++++++ 7 files changed, 148 insertions(+), 17 deletions(-) create mode 100644 crates/cast/bin/cmd/artifact.rs diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index a16436dd2..6f17707d4 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -1,5 +1,5 @@ use crate::cmd::{ - access_list::AccessListArgs, bind::BindArgs, call::CallArgs, + access_list::AccessListArgs, artifact::ArtifactArgs, bind::BindArgs, call::CallArgs, constructor_args::ConstructorArgsArgs, create2::Create2Args, creation_code::CreationCodeArgs, estimate::EstimateArgs, find_block::FindBlockArgs, interface::InterfaceArgs, logs::LogsArgs, mktx::MakeTxArgs, rpc::RpcArgs, run::RunArgs, send::SendTxArgs, storage::StorageArgs, @@ -927,6 +927,10 @@ pub enum CastSubcommand { #[command(visible_alias = "cc")] CreationCode(CreationCodeArgs), + /// Generate an artifact file, that can be used to deploy a contract locally. + #[command(visible_alias = "ar")] + Artifact(ArtifactArgs), + /// Display constructor arguments used for the contract initialization. #[command(visible_alias = "cra")] ConstructorArgs(ConstructorArgsArgs), diff --git a/crates/cast/bin/cmd/artifact.rs b/crates/cast/bin/cmd/artifact.rs new file mode 100644 index 000000000..2e7a7cae0 --- /dev/null +++ b/crates/cast/bin/cmd/artifact.rs @@ -0,0 +1,95 @@ +use alloy_primitives::Address; +use alloy_provider::Provider; +use clap::{command, Parser}; +use eyre::Result; +use foundry_block_explorers::Client; +use foundry_cli::{ + opts::{EtherscanOpts, RpcOpts}, + utils, +}; +use foundry_common::fs; +use foundry_config::Config; +use serde_json::json; +use std::path::PathBuf; + +use super::{ + creation_code::{fetch_creation_code, parse_code_output}, + interface::{fetch_abi_from_etherscan, load_abi_from_file}, +}; + +/// CLI arguments for `cast artifact`. +#[derive(Parser)] +pub struct ArtifactArgs { + /// An Ethereum address, for which the artifact will be produced. + contract: Address, + + /// Path to file containing the contract's JSON ABI. It's necessary if the target contract is + /// not verified on Etherscan. + #[arg(long)] + abi_path: Option, + + /// The path to the output file. + /// + /// If not specified, the artifact will be output to stdout. + #[arg( + short, + long, + value_hint = clap::ValueHint::FilePath, + value_name = "PATH", + )] + output: Option, + + #[command(flatten)] + etherscan: EtherscanOpts, + + #[command(flatten)] + rpc: RpcOpts, +} + +impl ArtifactArgs { + pub async fn run(self) -> Result<()> { + let Self { contract, etherscan, rpc, output: output_location, abi_path } = self; + + let mut etherscan = etherscan; + let config = Config::from(&rpc); + let provider = utils::get_provider(&config)?; + let api_key = etherscan.key().unwrap_or_default(); + let chain = provider.get_chain_id().await?; + etherscan.chain = Some(chain.into()); + let client = Client::new(chain.into(), api_key)?; + + let abi = if let Some(ref abi_path) = abi_path { + load_abi_from_file(abi_path, None)? + } else { + fetch_abi_from_etherscan(contract, ðerscan).await? + }; + + let (abi, _) = abi.first().ok_or_else(|| eyre::eyre!("No ABI found"))?; + + let bytecode = fetch_creation_code(contract, client, provider).await?; + let bytecode = + parse_code_output(bytecode, contract, ðerscan, abi_path.as_deref(), true, false) + .await?; + + let artifact = json!({ + "abi": abi, + "bytecode": { + "object": bytecode + } + }); + + let artifact = serde_json::to_string_pretty(&artifact)?; + + if let Some(loc) = output_location { + if let Some(parent) = loc.parent() { + fs::create_dir_all(parent)?; + } + fs::write(&loc, artifact)?; + sh_println!("Saved artifact at {}", loc.display())?; + } else { + sh_println!("{artifact}")?; + } + + Ok(()) + } +} diff --git a/crates/cast/bin/cmd/constructor_args.rs b/crates/cast/bin/cmd/constructor_args.rs index b0a08704f..8fe42c93c 100644 --- a/crates/cast/bin/cmd/constructor_args.rs +++ b/crates/cast/bin/cmd/constructor_args.rs @@ -1,5 +1,6 @@ use alloy_dyn_abi::DynSolType; use alloy_primitives::{Address, Bytes}; +use alloy_provider::Provider; use clap::{command, Parser}; use eyre::{eyre, OptionExt, Result}; use foundry_block_explorers::Client; @@ -36,13 +37,13 @@ impl ConstructorArgsArgs { pub async fn run(self) -> Result<()> { let Self { contract, etherscan, rpc, abi_path } = self; - let config = Config::from(ðerscan); - let chain = config.chain.unwrap_or_default(); - let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let client = Client::new(chain, api_key)?; - + let mut etherscan = etherscan; let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; + let api_key = etherscan.key().unwrap_or_default(); + let chain = provider.get_chain_id().await?; + etherscan.chain = Some(chain.into()); + let client = Client::new(chain.into(), api_key)?; let bytecode = fetch_creation_code(contract, client, provider).await?; diff --git a/crates/cast/bin/cmd/creation_code.rs b/crates/cast/bin/cmd/creation_code.rs index bcafeac94..04531b616 100644 --- a/crates/cast/bin/cmd/creation_code.rs +++ b/crates/cast/bin/cmd/creation_code.rs @@ -49,19 +49,25 @@ impl CreationCodeArgs { let Self { contract, etherscan, rpc, disassemble, without_args, only_args, abi_path } = self; - let config = Config::from(ðerscan); - let chain = config.chain.unwrap_or_default(); - let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); - let client = Client::new(chain, api_key)?; - + let mut etherscan = etherscan; let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; + let api_key = etherscan.key().unwrap_or_default(); + let chain = provider.get_chain_id().await?; + etherscan.chain = Some(chain.into()); + let client = Client::new(chain.into(), api_key)?; let bytecode = fetch_creation_code(contract, client, provider).await?; - let bytecode = - parse_code_output(bytecode, contract, ðerscan, abi_path, without_args, only_args) - .await?; + let bytecode = parse_code_output( + bytecode, + contract, + ðerscan, + abi_path.as_deref(), + without_args, + only_args, + ) + .await?; if disassemble { let _ = sh_println!("{}", SimpleCast::disassemble(&bytecode)?); @@ -77,11 +83,11 @@ impl CreationCodeArgs { /// - The complete bytecode /// - The bytecode without constructor arguments /// - Only the constructor arguments -async fn parse_code_output( +pub async fn parse_code_output( bytecode: Bytes, contract: Address, etherscan: &EtherscanOpts, - abi_path: Option, + abi_path: Option<&str>, without_args: bool, only_args: bool, ) -> Result { @@ -90,7 +96,7 @@ async fn parse_code_output( } let abi = if let Some(abi_path) = abi_path { - load_abi_from_file(&abi_path, None)? + load_abi_from_file(abi_path, None)? } else { fetch_abi_from_etherscan(contract, etherscan).await? }; diff --git a/crates/cast/bin/cmd/mod.rs b/crates/cast/bin/cmd/mod.rs index 49e3ed2ef..3f57b7668 100644 --- a/crates/cast/bin/cmd/mod.rs +++ b/crates/cast/bin/cmd/mod.rs @@ -6,6 +6,7 @@ //! [`foundry_config::Config`]. pub mod access_list; +pub mod artifact; pub mod bind; pub mod call; pub mod constructor_args; diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index cdeaad2d2..2eac8682c 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -213,6 +213,7 @@ async fn main_args(args: CastArgs) -> Result<()> { CastSubcommand::Interface(cmd) => cmd.run().await?, CastSubcommand::CreationCode(cmd) => cmd.run().await?, CastSubcommand::ConstructorArgs(cmd) => cmd.run().await?, + CastSubcommand::Artifact(cmd) => cmd.run().await?, CastSubcommand::Bind(cmd) => cmd.run().await?, CastSubcommand::PrettyCalldata { calldata, offline } => { let calldata = stdin::unwrap_line(calldata)?; diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 29527f7dc..058c52aec 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1528,3 +1528,26 @@ Traces: "#]]); }); + +// tests that displays a sample contract artifact +// +casttest!(fetch_artifact_from_etherscan, |_prj, cmd| { + let eth_rpc_url = next_http_rpc_endpoint(); + cmd.args([ + "artifact", + "--etherscan-api-key", + &next_mainnet_etherscan_api_key(), + "0x0923cad07f06b2d0e5e49e63b8b35738d4156b95", + "--rpc-url", + eth_rpc_url.as_str(), + ]) + .assert_success() + .stdout_eq(str![[r#"{ + "abi": [], + "bytecode": { + "object": "0x60566050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122074c61e8e4eefd410ca92eec26e8112ec6e831d0a4bf35718fdd78b45d68220d064736f6c63430008070033" + } +} + +"#]]); +}); From 4817280d96e0e33a2e96cf169770da60514d1764 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:39:37 +0200 Subject: [PATCH 17/58] fix(fork): set block blob_excess_gas_and_price only if `excess_blob_gas header` is Some (#9298) fix(fork): set block blob_excess_gas_and_price only if excess_blob_gas header is Some --- crates/evm/core/src/backend/mod.rs | 5 +++-- crates/forge/tests/cli/test_cmd.rs | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index e0b35f0bd..c9bb89047 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -1922,8 +1922,9 @@ fn update_env_block(env: &mut Env, block: &Block) { env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); env.block.gas_limit = U256::from(block.header.gas_limit); env.block.number = U256::from(block.header.number); - env.block.blob_excess_gas_and_price = - block.header.excess_blob_gas.map(BlobExcessGasAndPrice::new); + if let Some(excess_blob_gas) = block.header.excess_blob_gas { + env.block.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(excess_blob_gas)); + } } /// Executes the given transaction and commits state changes to the database _and_ the journaled diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index b952e19bd..8389c381e 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -2616,3 +2616,26 @@ forgetest_async!(can_get_broadcast_txs, |prj, cmd| { cmd.forge_fuse().args(["test", "--mc", "GetBroadcastTest", "-vvv"]).assert_success(); }); + +// See +forgetest_init!(test_roll_scroll_fork_with_cancun, |prj, cmd| { + prj.add_test( + "ScrollForkTest.t.sol", + r#" + +import {Test} from "forge-std/Test.sol"; + +contract ScrollForkTest is Test { + function test_roll_scroll_fork_to_tx() public { + vm.createSelectFork("https://scroll-mainnet.chainstacklabs.com/"); + bytes32 targetTxHash = 0xf94774a1f69bba76892141190293ffe85dd8d9ac90a0a2e2b114b8c65764014c; + vm.rollFork(targetTxHash); + } +} + "#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_roll_scroll_fork_to_tx", "--evm-version", "cancun"]) + .assert_success(); +}); From 22cf683acf04180a96f4a4435fa34da34a502874 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:59:27 +0100 Subject: [PATCH 18/58] feat(`common::shell`): add global verbosity level (`-vvv`) flag replacing `--verbose` (#9273) * remove --verbose, prefer output mode, introduce verbosity level (-vvv) * remove leftover * fix arg * add ability to set verbosity level * fix tests * remove evm args specific verbosity arg in favor of global arg due to Clap limitation * revert test modifications from https://github.com/foundry-rs/foundry/pull/9244 for TestArgs, simply pass + flatten ShellOpts in args * in lieu of a context specific help document the verbosity levels of the EVM as an example * format comment, update tests * fix clippy --- crates/cast/bin/args.rs | 4 +- crates/cast/bin/cmd/run.rs | 8 +- crates/cast/bin/cmd/wallet/mod.rs | 7 +- crates/cast/tests/cli/main.rs | 16 +++- crates/cli/src/opts/shell.rs | 43 +++++------ crates/common/src/evm.rs | 21 ++---- crates/common/src/io/shell.rs | 117 ++++++++++++++++-------------- crates/forge/bin/cmd/compiler.rs | 34 +++------ crates/forge/bin/cmd/config.rs | 10 +-- crates/forge/bin/cmd/test/mod.rs | 48 +++--------- crates/forge/tests/cli/cmd.rs | 16 +++- crates/script/src/lib.rs | 8 +- 12 files changed, 152 insertions(+), 180 deletions(-) diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index 6f17707d4..8bb7f2d54 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -793,7 +793,7 @@ pub enum CastSubcommand { who: Option, /// Perform a reverse lookup to verify that the name is correct. - #[arg(long, short)] + #[arg(long)] verify: bool, #[command(flatten)] @@ -807,7 +807,7 @@ pub enum CastSubcommand { who: Option
, /// Perform a normal lookup to verify that the address is correct. - #[arg(long, short)] + #[arg(long)] verify: bool, #[command(flatten)] diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 7389d1f35..880b2fe6f 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -8,7 +8,7 @@ use foundry_cli::{ opts::{EtherscanOpts, RpcOpts}, utils::{handle_traces, init_progress, TraceResult}, }; -use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; +use foundry_common::{is_known_system_sender, shell, SYSTEM_TRANSACTION_TYPE}; use foundry_compilers::artifacts::EvmVersion; use foundry_config::{ figment::{ @@ -48,10 +48,6 @@ pub struct RunArgs { #[arg(long)] quick: bool, - /// Prints the full address of the contract. - #[arg(long, short)] - verbose: bool, - /// Label addresses in the trace. /// /// Example: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045:vitalik.eth @@ -252,7 +248,7 @@ impl RunArgs { self.label, self.debug, self.decode_internal, - self.verbose, + shell::verbosity() > 0, ) .await?; diff --git a/crates/cast/bin/cmd/wallet/mod.rs b/crates/cast/bin/cmd/wallet/mod.rs index 8023b8bdf..b6dea48e1 100644 --- a/crates/cast/bin/cmd/wallet/mod.rs +++ b/crates/cast/bin/cmd/wallet/mod.rs @@ -183,10 +183,6 @@ pub enum WalletSubcommands { #[arg(value_name = "MNEMONIC_INDEX_OR_DERIVATION_PATH")] mnemonic_index_or_derivation_path_override: Option, - /// Verbose mode, print the address and private key. - #[arg(short = 'v', long)] - verbose: bool, - #[command(flatten)] wallet: WalletOpts, }, @@ -462,7 +458,6 @@ flag to set your key via: wallet, mnemonic_override, mnemonic_index_or_derivation_path_override, - verbose, } => { let (index_override, derivation_path_override) = match mnemonic_index_or_derivation_path_override { @@ -485,7 +480,7 @@ flag to set your key via: .await?; match wallet { WalletSigner::Local(wallet) => { - if verbose { + if shell::verbosity() > 0 { sh_println!("Address: {}", wallet.address())?; sh_println!( "Private key: 0x{}", diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 058c52aec..bec345b17 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -33,7 +33,7 @@ Options: Display options: --color - Log messages coloring + The color of the log messages Possible values: - auto: Intelligently guess whether to use color output (default) @@ -46,8 +46,18 @@ Display options: -q, --quiet Do not print log messages - --verbose - Use verbose output + -v, --verbosity... + Verbosity level of the log messages. + + Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + + Depending on the context the verbosity levels have different meanings. + + For example, the verbosity levels of the EVM are: + - 2 (-vv): Print logs for all tests. + - 3 (-vvv): Print execution traces for failing tests. + - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + - 5 (-vvvvv): Print execution and setup traces for all tests. Find more information in the book: http://book.getfoundry.sh/reference/cast/cast.html diff --git a/crates/cli/src/opts/shell.rs b/crates/cli/src/opts/shell.rs index fd83b952b..e559cc0f2 100644 --- a/crates/cli/src/opts/shell.rs +++ b/crates/cli/src/opts/shell.rs @@ -1,24 +1,27 @@ -use clap::Parser; -use foundry_common::shell::{ColorChoice, OutputFormat, Shell, Verbosity}; +use clap::{ArgAction, Parser}; +use foundry_common::shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbosity}; // note: `verbose` and `quiet` cannot have `short` because of conflicts with multiple commands. /// Global shell options. -#[derive(Clone, Copy, Debug, Parser)] +#[derive(Clone, Copy, Debug, Default, Parser)] pub struct ShellOpts { - /// Use verbose output. - #[clap(long, global = true, conflicts_with = "quiet", help_heading = "Display options")] - pub verbose: bool, + /// Verbosity level of the log messages. + /// + /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + /// + /// Depending on the context the verbosity levels have different meanings. + /// + /// For example, the verbosity levels of the EVM are: + /// - 2 (-vv): Print logs for all tests. + /// - 3 (-vvv): Print execution traces for failing tests. + /// - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + /// - 5 (-vvvvv): Print execution and setup traces for all tests. + #[clap(short, long, global = true, verbatim_doc_comment, conflicts_with = "quiet", action = ArgAction::Count, help_heading = "Display options")] + pub verbosity: Verbosity, /// Do not print log messages. - #[clap( - short, - long, - global = true, - alias = "silent", - conflicts_with = "verbose", - help_heading = "Display options" - )] + #[clap(short, long, global = true, alias = "silent", help_heading = "Display options")] pub quiet: bool, /// Format log messages as JSON. @@ -31,18 +34,16 @@ pub struct ShellOpts { )] pub json: bool, - /// Log messages coloring. + /// The color of the log messages. #[clap(long, global = true, value_enum, help_heading = "Display options")] pub color: Option, } impl ShellOpts { pub fn shell(self) -> Shell { - let verbosity = match (self.verbose, self.quiet) { - (true, false) => Verbosity::Verbose, - (false, true) => Verbosity::Quiet, - (false, false) => Verbosity::Normal, - (true, true) => unreachable!(), + let mode = match self.quiet { + true => OutputMode::Quiet, + false => OutputMode::Normal, }; let color = self.json.then_some(ColorChoice::Never).or(self.color).unwrap_or_default(); let format = match self.json { @@ -50,6 +51,6 @@ impl ShellOpts { false => OutputFormat::Text, }; - Shell::new_with(format, color, verbosity) + Shell::new_with(format, mode, color, self.verbosity) } } diff --git a/crates/common/src/evm.rs b/crates/common/src/evm.rs index e738cc6dd..3eca0800e 100644 --- a/crates/common/src/evm.rs +++ b/crates/common/src/evm.rs @@ -1,7 +1,7 @@ //! CLI arguments for configuring the EVM settings. use alloy_primitives::{map::HashMap, Address, B256, U256}; -use clap::{ArgAction, Parser}; +use clap::Parser; use eyre::ContextCompat; use foundry_config::{ figment::{ @@ -14,6 +14,8 @@ use foundry_config::{ }; use serde::Serialize; +use crate::shell; + /// Map keyed by breakpoints char to their location (contract address, pc) pub type Breakpoints = HashMap; @@ -101,19 +103,6 @@ pub struct EvmArgs { #[serde(skip)] pub always_use_create_2_factory: bool, - /// Verbosity of the EVM. - /// - /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). - /// - /// Verbosity levels: - /// - 2: Print logs for all tests - /// - 3: Print execution traces for failing tests - /// - 4: Print execution traces for all tests, and setup traces for failing tests - /// - 5: Print execution and setup traces for all tests - #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count)] - #[serde(skip)] - pub verbosity: u8, - /// Sets the number of assumed available compute units per second for this provider /// /// default value: 330 @@ -163,9 +152,9 @@ impl Provider for EvmArgs { let error = InvalidType(value.to_actual(), "map".into()); let mut dict = value.into_dict().ok_or(error)?; - if self.verbosity > 0 { + if shell::verbosity() > 0 { // need to merge that manually otherwise `from_occurrences` does not work - dict.insert("verbosity".to_string(), self.verbosity.into()); + dict.insert("verbosity".to_string(), shell::verbosity().into()); } if self.ffi { diff --git a/crates/common/src/io/shell.rs b/crates/common/src/io/shell.rs index 45d9c2296..09a167df9 100644 --- a/crates/common/src/io/shell.rs +++ b/crates/common/src/io/shell.rs @@ -17,14 +17,19 @@ use std::{ }, }; -/// Returns the currently set verbosity. +/// Returns the currently set verbosity level. pub fn verbosity() -> Verbosity { Shell::get().verbosity() } -/// Returns whether the verbosity level is [`Verbosity::Quiet`]. +/// Set the verbosity level. +pub fn set_verbosity(verbosity: Verbosity) { + Shell::get().set_verbosity(verbosity); +} + +/// Returns whether the output mode is [`OutputMode::Quiet`]. pub fn is_quiet() -> bool { - verbosity().is_quiet() + Shell::get().output_mode().is_quiet() } /// Returns whether the output format is [`OutputFormat::Json`]. @@ -68,11 +73,9 @@ impl TtyWidth { } } -/// The requested verbosity of output. #[derive(Debug, Default, Clone, Copy, PartialEq)] -pub enum Verbosity { - /// All output - Verbose, +/// The requested output mode. +pub enum OutputMode { /// Default output #[default] Normal, @@ -80,20 +83,14 @@ pub enum Verbosity { Quiet, } -impl Verbosity { - /// Returns true if the verbosity level is `Verbose`. - #[inline] - pub fn is_verbose(self) -> bool { - self == Self::Verbose - } - - /// Returns true if the verbosity level is `Normal`. +impl OutputMode { + /// Returns true if the output mode is `Normal`. #[inline] pub fn is_normal(self) -> bool { self == Self::Normal } - /// Returns true if the verbosity level is `Quiet`. + /// Returns true if the output mode is `Quiet`. #[inline] pub fn is_quiet(self) -> bool { self == Self::Quiet @@ -124,6 +121,9 @@ impl OutputFormat { } } +/// The verbosity level. +pub type Verbosity = u8; + /// An abstraction around console output that remembers preferences for output /// verbosity and color. pub struct Shell { @@ -134,7 +134,10 @@ pub struct Shell { /// The format to use for message output. output_format: OutputFormat, - /// How verbose messages should be. + /// The verbosity mode to use for message output. + output_mode: OutputMode, + + /// The verbosity level to use for message output. verbosity: Verbosity, /// Flag that indicates the current line needs to be cleared before @@ -145,6 +148,8 @@ pub struct Shell { impl fmt::Debug for Shell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut s = f.debug_struct("Shell"); + s.field("output_format", &self.output_format); + s.field("output_mode", &self.output_mode); s.field("verbosity", &self.verbosity); if let ShellOut::Stream { color_choice, .. } = self.output { s.field("color_choice", &color_choice); @@ -190,12 +195,22 @@ impl Shell { /// output. #[inline] pub fn new() -> Self { - Self::new_with(OutputFormat::Text, ColorChoice::Auto, Verbosity::Verbose) + Self::new_with( + OutputFormat::Text, + OutputMode::Normal, + ColorChoice::Auto, + Verbosity::default(), + ) } /// Creates a new shell with the given color choice and verbosity. #[inline] - pub fn new_with(format: OutputFormat, color: ColorChoice, verbosity: Verbosity) -> Self { + pub fn new_with( + format: OutputFormat, + mode: OutputMode, + color: ColorChoice, + verbosity: Verbosity, + ) -> Self { Self { output: ShellOut::Stream { stdout: AutoStream::new(std::io::stdout(), color.to_anstream_color_choice()), @@ -204,6 +219,7 @@ impl Shell { stderr_tty: std::io::stderr().is_terminal(), }, output_format: format, + output_mode: mode, verbosity, needs_clear: AtomicBool::new(false), } @@ -215,7 +231,8 @@ impl Shell { Self { output: ShellOut::Empty(std::io::empty()), output_format: OutputFormat::Text, - verbosity: Verbosity::Quiet, + output_mode: OutputMode::Quiet, + verbosity: 0, needs_clear: AtomicBool::new(false), } } @@ -266,15 +283,27 @@ impl Shell { } } - /// Gets the verbosity of the shell. + /// Gets the output format of the shell. + #[inline] + pub fn output_format(&self) -> OutputFormat { + self.output_format + } + + /// Gets the output mode of the shell. + #[inline] + pub fn output_mode(&self) -> OutputMode { + self.output_mode + } + + /// Gets the verbosity of the shell when [`OutputMode::Normal`] is set. #[inline] pub fn verbosity(&self) -> Verbosity { self.verbosity } - /// Gets the output format of the shell. - pub fn output_format(&self) -> OutputFormat { - self.output_format + /// Sets the verbosity level. + pub fn set_verbosity(&mut self, verbosity: Verbosity) { + self.verbosity = verbosity; } /// Gets the current color choice. @@ -338,24 +367,6 @@ impl Shell { } } - /// Runs the callback only if we are in verbose mode. - #[inline] - pub fn verbose(&mut self, mut callback: impl FnMut(&mut Self) -> Result<()>) -> Result<()> { - match self.verbosity { - Verbosity::Verbose => callback(self), - _ => Ok(()), - } - } - - /// Runs the callback if we are not in verbose mode. - #[inline] - pub fn concise(&mut self, mut callback: impl FnMut(&mut Self) -> Result<()>) -> Result<()> { - match self.verbosity { - Verbosity::Verbose => Ok(()), - _ => callback(self), - } - } - /// Prints a red 'error' message. Use the [`sh_err!`] macro instead. /// This will render a message in [ERROR] style with a bold `Error: ` prefix. /// @@ -370,8 +381,8 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn warn(&mut self, message: impl fmt::Display) -> Result<()> { - match self.verbosity { - Verbosity::Quiet => Ok(()), + match self.output_mode { + OutputMode::Quiet => Ok(()), _ => self.print(&"Warning", &WARN, Some(&message), false), } } @@ -387,10 +398,9 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn print_out(&mut self, fragment: impl fmt::Display) -> Result<()> { - if self.verbosity == Verbosity::Quiet { - Ok(()) - } else { - self.write_stdout(fragment, &Style::new()) + match self.output_mode { + OutputMode::Quiet => Ok(()), + _ => self.write_stdout(fragment, &Style::new()), } } @@ -405,10 +415,9 @@ impl Shell { /// /// **Note**: if `verbosity` is set to `Quiet`, this is a no-op. pub fn print_err(&mut self, fragment: impl fmt::Display) -> Result<()> { - if self.verbosity == Verbosity::Quiet { - Ok(()) - } else { - self.write_stderr(fragment, &Style::new()) + match self.output_mode { + OutputMode::Quiet => Ok(()), + _ => self.write_stderr(fragment, &Style::new()), } } @@ -421,8 +430,8 @@ impl Shell { message: Option<&dyn fmt::Display>, justified: bool, ) -> Result<()> { - match self.verbosity { - Verbosity::Quiet => Ok(()), + match self.output_mode { + OutputMode::Quiet => Ok(()), _ => { self.maybe_err_erase_line(); self.output.message_stderr(status, style, message, justified) diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index 0b0ec171b..a7115c487 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -1,5 +1,6 @@ -use clap::{ArgAction, Parser, Subcommand, ValueHint}; +use clap::{Parser, Subcommand, ValueHint}; use eyre::Result; +use foundry_common::shell; use foundry_compilers::{artifacts::EvmVersion, Graph}; use foundry_config::Config; use semver::Version; @@ -51,26 +52,11 @@ pub struct ResolveArgs { /// Skip files that match the given regex pattern. #[arg(long, short, value_name = "REGEX")] skip: Option, - - /// Verbosity of the output. - /// - /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). - /// - /// Verbosity levels: - /// - 0: Print compiler versions. - /// - 1: Print compiler version and source paths. - /// - 2: Print compiler version, source paths and max supported EVM version of the compiler. - #[arg(long, short, verbatim_doc_comment, action = ArgAction::Count, help_heading = "Display options")] - pub verbosity: u8, - - /// Print as JSON. - #[arg(long, short, help_heading = "Display options")] - json: bool, } impl ResolveArgs { pub fn run(self) -> Result<()> { - let Self { root, skip, verbosity, json } = self; + let Self { root, skip } = self; let root = root.unwrap_or_else(|| PathBuf::from(".")); let config = Config::load_with_root(&root); @@ -110,7 +96,7 @@ impl ResolveArgs { }) .collect(); - let evm_version = if verbosity > 1 { + let evm_version = if shell::verbosity() > 1 { Some( EvmVersion::default() .normalize_version_solc(version) @@ -132,7 +118,7 @@ impl ResolveArgs { if !versions_with_paths.is_empty() { // Clear paths if verbosity is 0, performed only after filtering to avoid being // skipped. - if verbosity == 0 { + if shell::verbosity() == 0 { versions_with_paths.iter_mut().for_each(|version| version.paths.clear()); } @@ -140,20 +126,20 @@ impl ResolveArgs { } } - if json { + if shell::is_json() { sh_println!("{}", serde_json::to_string(&output)?)?; return Ok(()); } for (language, compilers) in &output { - match verbosity { + match shell::verbosity() { 0 => sh_println!("{language}:")?, _ => sh_println!("{language}:\n")?, } for resolved_compiler in compilers { let version = &resolved_compiler.version; - match verbosity { + match shell::verbosity() { 0 => sh_println!("- {version}")?, _ => { if let Some(evm) = &resolved_compiler.evm_version { @@ -164,7 +150,7 @@ impl ResolveArgs { } } - if verbosity > 0 { + if shell::verbosity() > 0 { let paths = &resolved_compiler.paths; for (idx, path) in paths.iter().enumerate() { if idx == paths.len() - 1 { @@ -176,7 +162,7 @@ impl ResolveArgs { } } - if verbosity == 0 { + if shell::verbosity() == 0 { sh_println!()? } } diff --git a/crates/forge/bin/cmd/config.rs b/crates/forge/bin/cmd/config.rs index 652c5a10f..36f4d1731 100644 --- a/crates/forge/bin/cmd/config.rs +++ b/crates/forge/bin/cmd/config.rs @@ -2,7 +2,7 @@ use super::build::BuildArgs; use clap::Parser; use eyre::Result; use foundry_cli::utils::LoadConfig; -use foundry_common::evm::EvmArgs; +use foundry_common::{evm::EvmArgs, shell}; use foundry_config::fix::fix_tomls; foundry_config::impl_figment_convert!(ConfigArgs, opts, evm_opts); @@ -14,10 +14,6 @@ pub struct ConfigArgs { #[arg(long)] basic: bool, - /// Print currently set config values as JSON. - #[arg(long)] - json: bool, - /// Attempt to fix any configuration warnings. #[arg(long)] fix: bool, @@ -46,12 +42,12 @@ impl ConfigArgs { let s = if self.basic { let config = config.into_basic(); - if self.json { + if shell::is_json() { serde_json::to_string_pretty(&config)? } else { config.to_string_pretty()? } - } else if self.json { + } else if shell::is_json() { serde_json::to_string_pretty(&config)? } else { config.to_string_pretty()? diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 091599305..77ae5d263 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -17,7 +17,7 @@ use forge::{ MultiContractRunner, MultiContractRunnerBuilder, TestFilter, TestOptions, TestOptionsBuilder, }; use foundry_cli::{ - opts::CoreBuildArgs, + opts::{CoreBuildArgs, ShellOpts}, utils::{self, LoadConfig}, }; use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell, TestFunctionExt}; @@ -178,6 +178,9 @@ pub struct TestArgs { /// Print detailed test summary table. #[arg(long, help_heading = "Display options", requires = "summary")] pub detailed: bool, + + #[command(flatten)] + shell: ShellOpts, } impl TestArgs { @@ -993,56 +996,34 @@ fn junit_xml_report(results: &BTreeMap, verbosity: u8) -> R #[cfg(test)] mod tests { - use crate::opts::{Forge, ForgeSubcommand}; - use super::*; use foundry_config::{Chain, InvariantConfig}; use foundry_test_utils::forgetest_async; #[test] fn watch_parse() { - let args = match Forge::parse_from(["foundry-cli", "test", "-vw"]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = TestArgs::parse_from(["foundry-cli", "-vw"]); assert!(args.watch.watch.is_some()); } #[test] fn fuzz_seed() { - let args = match Forge::parse_from(["foundry-cli", "test", "--fuzz-seed", "0x10"]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = TestArgs::parse_from(["foundry-cli", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } // #[test] fn fuzz_seed_exists() { - let args = match Forge::parse_from([ - "foundry-cli", - "test", - "-vvv", - "--gas-report", - "--fuzz-seed", - "0x10", - ]) - .cmd - { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args: TestArgs = + TestArgs::parse_from(["foundry-cli", "-vvv", "--gas-report", "--fuzz-seed", "0x10"]); assert!(args.fuzz_seed.is_some()); } #[test] fn extract_chain() { let test = |arg: &str, expected: Chain| { - let args = match Forge::parse_from(["foundry-cli", "test", arg]).cmd { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; + let args = TestArgs::parse_from(["foundry-cli", arg]); assert_eq!(args.evm_opts.env.chain, Some(expected)); let (config, evm_opts) = args.load_config_and_evm_opts().unwrap(); assert_eq!(config.chain, Some(expected)); @@ -1096,19 +1077,12 @@ contract FooBarTest is DSTest { ) .unwrap(); - let args = match Forge::parse_from([ + let args = TestArgs::parse_from([ "foundry-cli", - "test", "--gas-report", "--root", &prj.root().to_string_lossy(), - ]) - .cmd - { - ForgeSubcommand::Test(args) => args, - _ => unreachable!(), - }; - + ]); let outcome = args.run().await.unwrap(); let gas_report = outcome.gas_report.unwrap(); diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 89335a492..9e9e1fda1 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -38,7 +38,7 @@ Options: Display options: --color - Log messages coloring + The color of the log messages Possible values: - auto: Intelligently guess whether to use color output (default) @@ -51,8 +51,18 @@ Display options: -q, --quiet Do not print log messages - --verbose - Use verbose output + -v, --verbosity... + Verbosity level of the log messages. + + Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). + + Depending on the context the verbosity levels have different meanings. + + For example, the verbosity levels of the EVM are: + - 2 (-vv): Print logs for all tests. + - 3 (-vvv): Print execution traces for failing tests. + - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. + - 5 (-vvvvv): Print execution and setup traces for all tests. Find more information in the book: http://book.getfoundry.sh/reference/forge/forge.html diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 707399d63..180a09647 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -26,7 +26,10 @@ use dialoguer::Confirm; use eyre::{ContextCompat, Result}; use forge_script_sequence::{AdditionalContract, NestedValue}; use forge_verify::RetryArgs; -use foundry_cli::{opts::CoreBuildArgs, utils::LoadConfig}; +use foundry_cli::{ + opts::{CoreBuildArgs, ShellOpts}, + utils::LoadConfig, +}; use foundry_common::{ abi::{encode_function_args, get_func}, evm::{Breakpoints, EvmArgs}, @@ -210,6 +213,9 @@ pub struct ScriptArgs { #[command(flatten)] pub retry: RetryArgs, + + #[clap(flatten)] + pub shell: ShellOpts, } impl ScriptArgs { From 40fc54eda8b905a00bf8c96250b0e0af9869de67 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Wed, 13 Nov 2024 13:39:02 +0200 Subject: [PATCH 19/58] chore: do not trim decoded generic custom error (#9309) chore: do not trim generic custom error trace --- crates/evm/core/src/decode.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/evm/core/src/decode.rs b/crates/evm/core/src/decode.rs index d6e8b3dec..c0ff33164 100644 --- a/crates/evm/core/src/decode.rs +++ b/crates/evm/core/src/decode.rs @@ -191,7 +191,7 @@ impl RevertDecoder { s.push_str(": "); match std::str::from_utf8(data) { Ok(data) => s.push_str(data), - Err(_) => s.push_str(&trimmed_hex(data)), + Err(_) => s.push_str(&hex::encode(data)), } } s From 54ea38d189bf192f689aed4c6f231a27f1def316 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Wed, 13 Nov 2024 15:36:15 +0200 Subject: [PATCH 20/58] fix(forge): always report deployment size in gas reports (#9308) --- crates/forge/src/gas_report.rs | 29 ++++---- crates/forge/tests/cli/cmd.rs | 126 +++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 14 deletions(-) diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index 1b6e4bd63..e3e44994b 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -94,31 +94,32 @@ impl GasReport { return; } - // Only include top-level calls which account for calldata and base (21.000) cost. - // Only include Calls and Creates as only these calls are isolated in inspector. - if trace.depth > 1 && - (trace.kind == CallKind::Call || - trace.kind == CallKind::Create || - trace.kind == CallKind::Create2 || - trace.kind == CallKind::EOFCreate) - { - return; - } - let Some(name) = decoder.contracts.get(&node.trace.address) else { return }; let contract_name = name.rsplit(':').next().unwrap_or(name); if !self.should_report(contract_name) { return; } + let contract_info = self.contracts.entry(name.to_string()).or_default(); + let is_create_call = trace.kind.is_any_create(); + + // Record contract deployment size. + if is_create_call { + trace!(contract_name, "adding create size info"); + contract_info.size = trace.data.len(); + } + + // Only include top-level calls which account for calldata and base (21.000) cost. + // Only include Calls and Creates as only these calls are isolated in inspector. + if trace.depth > 1 && (trace.kind == CallKind::Call || is_create_call) { + return; + } let decoded = || decoder.decode_function(&node.trace); - let contract_info = self.contracts.entry(name.to_string()).or_default(); - if trace.kind.is_any_create() { + if is_create_call { trace!(contract_name, "adding create gas info"); contract_info.gas = trace.gas_used; - contract_info.size = trace.data.len(); } else if let Some(DecodedCallData { signature, .. }) = decoded().await.call_data { let name = signature.split('(').next().unwrap(); // ignore any test/setup functions diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 9e9e1fda1..d4f3973a3 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -2544,6 +2544,132 @@ Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] ); }); +// +forgetest_init!(gas_report_size_for_nested_create, |prj, cmd| { + prj.add_test( + "NestedDeployTest.sol", + r#" +import {Test} from "forge-std/Test.sol"; +contract Child { + AnotherChild public child; + constructor() { + child = new AnotherChild(); + } + function w() external { + child.w(); + } +} +contract AnotherChild { + function w() external {} +} +contract Parent { + Child public immutable child; + constructor() { + child = new Child(); + } +} +contract NestedDeploy is Test { + function test_nested_create_gas_report() external { + Parent p = new Parent(); + p.child().child().w(); + } +} +"#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_nested_create_gas_report", "--gas-report"]) + .assert_success() + .stdout_eq(str![[r#" +... +Ran 1 test for test/NestedDeployTest.sol:NestedDeploy +[PASS] test_nested_create_gas_report() ([GAS]) +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] +| test/NestedDeployTest.sol:AnotherChild contract | | | | | | +|-------------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 0 | 130 | | | | | +| Function Name | min | avg | median | max | # calls | +| w | 21162 | 21162 | 21162 | 21162 | 1 | + + +| test/NestedDeployTest.sol:Child contract | | | | | | +|------------------------------------------|-----------------|-----|--------|-----|---------| +| Deployment Cost | Deployment Size | | | | | +| 0 | 498 | | | | | +| Function Name | min | avg | median | max | # calls | +| child | 325 | 325 | 325 | 325 | 1 | + + +| test/NestedDeployTest.sol:Parent contract | | | | | | +|-------------------------------------------|-----------------|-----|--------|-----|---------| +| Deployment Cost | Deployment Size | | | | | +| 254857 | 770 | | | | | +| Function Name | min | avg | median | max | # calls | +| child | 182 | 182 | 182 | 182 | 1 | +... +"#]]); + + cmd.forge_fuse() + .args(["test", "--mt", "test_nested_create_gas_report", "--gas-report", "--json"]) + .assert_success() + .stdout_eq( + str![[r#" +[ + { + "contract": "test/NestedDeployTest.sol:AnotherChild", + "deployment": { + "gas": 0, + "size": 130 + }, + "functions": { + "w()": { + "calls": 1, + "min": 21162, + "mean": 21162, + "median": 21162, + "max": 21162 + } + } + }, + { + "contract": "test/NestedDeployTest.sol:Child", + "deployment": { + "gas": 0, + "size": 498 + }, + "functions": { + "child()": { + "calls": 1, + "min": 325, + "mean": 325, + "median": 325, + "max": 325 + } + } + }, + { + "contract": "test/NestedDeployTest.sol:Parent", + "deployment": { + "gas": 254857, + "size": 770 + }, + "functions": { + "child()": { + "calls": 1, + "min": 182, + "mean": 182, + "median": 182, + "max": 182 + } + } + } +] +"#]] + .is_json(), + ); +}); + forgetest_init!(can_use_absolute_imports, |prj, cmd| { let remapping = prj.paths().libraries[0].join("myDependency"); let config = Config { From 4304926fe0834af65a5cbc9b26c869e8c748d097 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Wed, 13 Nov 2024 16:45:07 +0100 Subject: [PATCH 21/58] fix(`ci`): update cargo deny (#9314) fix cargo deny --- deny.toml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/deny.toml b/deny.toml index b932b0388..031bc56e2 100644 --- a/deny.toml +++ b/deny.toml @@ -5,11 +5,12 @@ version = 2 yanked = "warn" ignore = [ - # https://github.com/watchexec/watchexec/issues/852 - "RUSTSEC-2024-0350", - "RUSTSEC-2024-0351", # proc-macro-error is unmaintained "RUSTSEC-2024-0370", + # instant is unmaintained + "RUSTSEC-2024-0384", + # derivative is unmaintained + "RUSTSEC-2024-0388", ] # This section is considered when running `cargo deny check bans`. @@ -45,6 +46,7 @@ allow = [ "BSD-2-Clause", "BSD-3-Clause", "ISC", + "Unicode-3.0", "Unicode-DFS-2016", "OpenSSL", "Unlicense", @@ -67,9 +69,6 @@ exceptions = [ { allow = ["CC0-1.0"], name = "notify" }, { allow = ["CC0-1.0"], name = "dunce" }, { allow = ["CC0-1.0"], name = "aurora-engine-modexp" }, - { allow = ["CC0-1.0"], name = "constant_time_eq" }, - { allow = ["CC0-1.0"], name = "secp256k1" }, - { allow = ["CC0-1.0"], name = "secp256k1-sys" }, ] #copyleft = "deny" From 78d263af61f37737c2f69fd94ec7fb8d2fc73987 Mon Sep 17 00:00:00 2001 From: m4rio <92288535+mario-eth@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:00:06 +0200 Subject: [PATCH 22/58] feat: Update to soldeer 0.5.1 (#9315) Update to soldeer 0.5.1 Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b18148fe9..0c9a611b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8348,9 +8348,9 @@ dependencies = [ [[package]] name = "soldeer-commands" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1925813f3dd013d212fa9ad184911846f99236dbfc8a6d79c8a54dfa0bb1a948" +checksum = "f5969c09f89ae6f0e18d5904e5bdbb8842ba948dad0f8202edb7ea510e35654d" dependencies = [ "bon", "clap", diff --git a/Cargo.toml b/Cargo.toml index 7754de503..0c0962a2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -278,7 +278,7 @@ semver = "1" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", features = ["arbitrary_precision"] } similar-asserts = "1.6" -soldeer-commands = "=0.5.0" +soldeer-commands = "=0.5.1" strum = "0.26" tempfile = "3.13" tikv-jemallocator = "0.6" From 31c24b0b901d6fd393d52070221cccab54e45e80 Mon Sep 17 00:00:00 2001 From: "Valentin B." <703631+beeb@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:32:22 +0100 Subject: [PATCH 23/58] chore: update soldeer-core dependency (#9316) --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c9a611b4..af730814c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8363,9 +8363,9 @@ dependencies = [ [[package]] name = "soldeer-core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b034d411ea9d1cd9bd77fa2978a42e4c4ae486f47738a545079f11a32c879" +checksum = "e63aeee0e78b5fba04f005d23a58d20f897720212bd21ad744201cacb9dd34f8" dependencies = [ "bon", "chrono", @@ -9193,7 +9193,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3637e734239e12ab152cd269302500bd063f37624ee210cd04b4936ed671f3b1" dependencies = [ "cc", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -9716,7 +9716,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] From a65a5b1445ba7ec9b10baf7ecb28f7a65bbb13ce Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Thu, 14 Nov 2024 13:12:27 +0400 Subject: [PATCH 24/58] fix(`forge eip712`): handle recursive types (#9319) fix(forge eip712): handle recursive types --- crates/forge/bin/cmd/eip712.rs | 23 +++++++++++++---------- crates/forge/tests/cli/eip712.rs | 32 +++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/crates/forge/bin/cmd/eip712.rs b/crates/forge/bin/cmd/eip712.rs index 2ab15f054..5014d38d7 100644 --- a/crates/forge/bin/cmd/eip712.rs +++ b/crates/forge/bin/cmd/eip712.rs @@ -126,7 +126,9 @@ impl Resolver { /// Returns `None` if struct contains any fields that are not supported by EIP-712 (e.g. /// mappings or function pointers). pub fn resolve_struct_eip712(&self, id: usize) -> Result> { - self.resolve_eip712_inner(id, &mut Default::default(), true, None) + let mut subtypes = BTreeMap::new(); + subtypes.insert(self.structs[&id].name.clone(), id); + self.resolve_eip712_inner(id, &mut subtypes, true, None) } fn resolve_eip712_inner( @@ -205,8 +207,17 @@ impl Resolver { // If we've already seen struct with this ID, just use assigned name. if let Some((name, _)) = subtypes.iter().find(|(_, id)| **id == def.id) { name.clone() - // Otherwise, try assigning a new name. } else { + // Otherwise, assign new name. + let mut i = 0; + let mut name = def.name.clone(); + while subtypes.contains_key(&name) { + i += 1; + name = format!("{}_{i}", def.name); + } + + subtypes.insert(name.clone(), def.id); + // iterate over members to check if they are resolvable and to populate subtypes for member in &def.members { if self.resolve_type( @@ -218,14 +229,6 @@ impl Resolver { return Ok(None) } } - let mut i = 0; - let mut name = def.name.clone(); - while subtypes.contains_key(&name) { - i += 1; - name = format!("{}_{i}", def.name); - } - - subtypes.insert(name.clone(), def.id); name }; diff --git a/crates/forge/tests/cli/eip712.rs b/crates/forge/tests/cli/eip712.rs index 2f832ae31..9ec944631 100644 --- a/crates/forge/tests/cli/eip712.rs +++ b/crates/forge/tests/cli/eip712.rs @@ -19,6 +19,11 @@ library Structs { struct Complex { Structs2.Foo foo2; Foo[] foos; + Rec[][] recs; + } + + struct Rec { + Rec[] rec; } } @@ -26,6 +31,23 @@ library Structs2 { struct Foo { uint256 id; } + + struct Rec { + Bar[] bar; + } + + struct Bar { + Rec rec; + } + + struct FooBar { + Foo[] foos; + Bar[] bars; + Structs.Foo foo; + Structs.Bar bar; + Rec[] recs; + Structs.Rec rec; + } } "#, ) @@ -42,10 +64,18 @@ Bar(Art art)Art(uint256 id) Art(uint256 id) -Complex(Foo foo2,Foo_1[] foos)Art(uint256 id)Bar(Art art)Foo(uint256 id)Foo_1(Bar bar) +Complex(Foo foo2,Foo_1[] foos,Rec[][] recs)Art(uint256 id)Bar(Art art)Foo(uint256 id)Foo_1(Bar bar)Rec(Rec[] rec) + +Rec(Rec[] rec) Foo(uint256 id) +Rec(Bar[] bar)Bar(Rec rec) + +Bar(Rec rec)Rec(Bar[] bar) + +FooBar(Foo[] foos,Bar[] bars,Foo_1 foo,Bar_1 bar,Rec[] recs,Rec_1 rec)Art(uint256 id)Bar(Rec rec)Bar_1(Art art)Foo(uint256 id)Foo_1(Bar_1 bar)Rec(Bar[] bar)Rec_1(Rec_1[] rec) + "#]], ); From 36cbce7c78b56dd68359084a5d8b03f84efed8fb Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Thu, 14 Nov 2024 20:34:12 +0200 Subject: [PATCH 25/58] feat(forge): allow `--verifier custom` option (#9311) * feat(forge): allow `--verifier custom` option * Changes after review: add description of custom verifier, reorg err message, add custom verifier api key * Fix descriptions * Update crates/verify/src/provider.rs Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- crates/common/src/retry.rs | 2 +- crates/verify/src/bytecode.rs | 5 +++++ crates/verify/src/provider.rs | 7 +++++++ crates/verify/src/verify.rs | 17 +++++++++++++++-- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/crates/common/src/retry.rs b/crates/common/src/retry.rs index 7f649c7ed..59ba2055f 100644 --- a/crates/common/src/retry.rs +++ b/crates/common/src/retry.rs @@ -83,6 +83,6 @@ impl Retry { fn handle_err(&mut self, err: Error) { self.retries -= 1; - warn!("erroneous attempt ({} tries remaining): {}", self.retries, err.root_cause()); + let _ = sh_warn!("{} ({} tries remaining)", err.root_cause(), self.retries); } } diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index a8fc1ace7..0c3f9e5b0 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -96,6 +96,11 @@ impl figment::Provider for VerifyBytecodeArgs { &self, ) -> Result, figment::Error> { let mut dict = self.etherscan.dict(); + + if let Some(api_key) = &self.verifier.verifier_api_key { + dict.insert("etherscan_api_key".into(), api_key.as_str().into()); + } + if let Some(block) = &self.block { dict.insert("block".into(), figment::value::Value::serialize(block)?); } diff --git a/crates/verify/src/provider.rs b/crates/verify/src/provider.rs index 6e5b29d5e..bc01bd9e3 100644 --- a/crates/verify/src/provider.rs +++ b/crates/verify/src/provider.rs @@ -124,6 +124,7 @@ impl FromStr for VerificationProviderType { "s" | "sourcify" => Ok(Self::Sourcify), "b" | "blockscout" => Ok(Self::Blockscout), "o" | "oklink" => Ok(Self::Oklink), + "c" | "custom" => Ok(Self::Custom), _ => Err(format!("Unknown provider: {s}")), } } @@ -144,6 +145,9 @@ impl fmt::Display for VerificationProviderType { Self::Oklink => { write!(f, "oklink")?; } + Self::Custom => { + write!(f, "custom")?; + } }; Ok(()) } @@ -156,6 +160,8 @@ pub enum VerificationProviderType { Sourcify, Blockscout, Oklink, + /// Custom verification provider, requires compatibility with the Etherscan API. + Custom, } impl VerificationProviderType { @@ -171,6 +177,7 @@ impl VerificationProviderType { Self::Sourcify => Ok(Box::::default()), Self::Blockscout => Ok(Box::::default()), Self::Oklink => Ok(Box::::default()), + Self::Custom => Ok(Box::::default()), } } } diff --git a/crates/verify/src/verify.rs b/crates/verify/src/verify.rs index 5f3e55329..89cfd99aa 100644 --- a/crates/verify/src/verify.rs +++ b/crates/verify/src/verify.rs @@ -31,14 +31,22 @@ pub struct VerifierArgs { #[arg(long, help_heading = "Verifier options", default_value = "etherscan", value_enum)] pub verifier: VerificationProviderType, - /// The verifier URL, if using a custom provider + /// The verifier API KEY, if using a custom provider. + #[arg(long, help_heading = "Verifier options", env = "VERIFIER_API_KEY")] + pub verifier_api_key: Option, + + /// The verifier URL, if using a custom provider. #[arg(long, help_heading = "Verifier options", env = "VERIFIER_URL")] pub verifier_url: Option, } impl Default for VerifierArgs { fn default() -> Self { - Self { verifier: VerificationProviderType::Etherscan, verifier_url: None } + Self { + verifier: VerificationProviderType::Etherscan, + verifier_api_key: None, + verifier_url: None, + } } } @@ -162,6 +170,11 @@ impl figment::Provider for VerifyArgs { if self.via_ir { dict.insert("via_ir".to_string(), figment::value::Value::serialize(self.via_ir)?); } + + if let Some(api_key) = &self.verifier.verifier_api_key { + dict.insert("etherscan_api_key".into(), api_key.as_str().into()); + } + Ok(figment::value::Map::from([(Config::selected_profile(), dict)])) } } From c526cab8364fdf410fb8b04d256ca83d4dc632bf Mon Sep 17 00:00:00 2001 From: James <107906898+EdwardJES@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:02:44 +0700 Subject: [PATCH 26/58] feat(`cheatcodes`): add `delegatecall` to `prank`ing (#8863) * begin api and rough comments * impl cheatcode * add check for eoa * fix eoa check on each prank call * add to assets * prank compiling * delegate call working, storage not upating * delegate call working, some tidy up * add prank2 calls * impl remaining tests * formatting * forge fmt * add pranks to cheatcodes.json * run cargo cheats * If verbosity level is 1 or higher, it shows dirty files. * Fix, add EOA prank test * Revert "If verbosity level is 1 or higher, it shows dirty files." This reverts commit d03ac1d59acb8096b12f46dfb5a397bcc4d28ce9. * Fix test * apply on extdelegatecall --------- Co-authored-by: mgiagante <251503-mgiagante@users.noreply.gitlab.com> Co-authored-by: grandizzy --- crates/cheatcodes/assets/cheatcodes.json | 80 ++++++++++++++++ crates/cheatcodes/spec/src/vm.rs | 16 ++++ crates/cheatcodes/src/evm/prank.rs | 58 +++++++++++- crates/cheatcodes/src/inspector.rs | 15 ++- testdata/cheats/Vm.sol | 4 + testdata/default/cheats/Prank.t.sol | 114 +++++++++++++++++++++++ 6 files changed, 281 insertions(+), 6 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 41797106d..347d738e0 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -7182,6 +7182,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "prank_2", + "description": "Sets the *next* delegate call's `msg.sender` to be the input address.", + "declaration": "function prank(address msgSender, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "prank(address,bool)", + "selector": "0xa7f8bf5c", + "selectorBytes": [ + 167, + 248, + 191, + 92 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "prank_3", + "description": "Sets the *next* delegate call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.", + "declaration": "function prank(address msgSender, address txOrigin, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "prank(address,address,bool)", + "selector": "0x7d73d042", + "selectorBytes": [ + 125, + 115, + 208, + 66 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "prevrandao_0", @@ -9288,6 +9328,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "startPrank_2", + "description": "Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called.", + "declaration": "function startPrank(address msgSender, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "startPrank(address,bool)", + "selector": "0x1cc0b435", + "selectorBytes": [ + 28, + 192, + 180, + 53 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, + { + "func": { + "id": "startPrank_3", + "description": "Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.", + "declaration": "function startPrank(address msgSender, address txOrigin, bool delegateCall) external;", + "visibility": "external", + "mutability": "", + "signature": "startPrank(address,address,bool)", + "selector": "0x4eb859b5", + "selectorBytes": [ + 78, + 184, + 89, + 181 + ] + }, + "group": "evm", + "status": "stable", + "safety": "unsafe" + }, { "func": { "id": "startSnapshotGas_0", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 3c11cd53a..d703f48e7 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -600,6 +600,22 @@ interface Vm { #[cheatcode(group = Evm, safety = Unsafe)] function startPrank(address msgSender, address txOrigin) external; + /// Sets the *next* delegate call's `msg.sender` to be the input address. + #[cheatcode(group = Evm, safety = Unsafe)] + function prank(address msgSender, bool delegateCall) external; + + /// Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called. + #[cheatcode(group = Evm, safety = Unsafe)] + function startPrank(address msgSender, bool delegateCall) external; + + /// Sets the *next* delegate call's `msg.sender` to be the input address, and the `tx.origin` to be the second input. + #[cheatcode(group = Evm, safety = Unsafe)] + function prank(address msgSender, address txOrigin, bool delegateCall) external; + + /// Sets all subsequent delegate calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input. + #[cheatcode(group = Evm, safety = Unsafe)] + function startPrank(address msgSender, address txOrigin, bool delegateCall) external; + /// Resets subsequent calls' `msg.sender` to be `address(this)`. #[cheatcode(group = Evm, safety = Unsafe)] function stopPrank() external; diff --git a/crates/cheatcodes/src/evm/prank.rs b/crates/cheatcodes/src/evm/prank.rs index a310e28e5..1d7ca5a07 100644 --- a/crates/cheatcodes/src/evm/prank.rs +++ b/crates/cheatcodes/src/evm/prank.rs @@ -16,6 +16,8 @@ pub struct Prank { pub depth: u64, /// Whether the prank stops by itself after the next call pub single_call: bool, + /// Whether the prank should be be applied to delegate call + pub delegate_call: bool, /// Whether the prank has been used yet (false if unused) pub used: bool, } @@ -29,8 +31,18 @@ impl Prank { new_origin: Option
, depth: u64, single_call: bool, + delegate_call: bool, ) -> Self { - Self { prank_caller, prank_origin, new_caller, new_origin, depth, single_call, used: false } + Self { + prank_caller, + prank_origin, + new_caller, + new_origin, + depth, + single_call, + delegate_call, + used: false, + } } /// Apply the prank by setting `used` to true iff it is false @@ -47,28 +59,56 @@ impl Prank { impl Cheatcode for prank_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender } = self; - prank(ccx, msgSender, None, true) + prank(ccx, msgSender, None, true, false) } } impl Cheatcode for startPrank_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender } = self; - prank(ccx, msgSender, None, false) + prank(ccx, msgSender, None, false, false) } } impl Cheatcode for prank_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender, txOrigin } = self; - prank(ccx, msgSender, Some(txOrigin), true) + prank(ccx, msgSender, Some(txOrigin), true, false) } } impl Cheatcode for startPrank_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { msgSender, txOrigin } = self; - prank(ccx, msgSender, Some(txOrigin), false) + prank(ccx, msgSender, Some(txOrigin), false, false) + } +} + +impl Cheatcode for prank_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, delegateCall } = self; + prank(ccx, msgSender, None, true, *delegateCall) + } +} + +impl Cheatcode for startPrank_2Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, delegateCall } = self; + prank(ccx, msgSender, None, false, *delegateCall) + } +} + +impl Cheatcode for prank_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, txOrigin, delegateCall } = self; + prank(ccx, msgSender, Some(txOrigin), true, *delegateCall) + } +} + +impl Cheatcode for startPrank_3Call { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { msgSender, txOrigin, delegateCall } = self; + prank(ccx, msgSender, Some(txOrigin), false, *delegateCall) } } @@ -85,6 +125,7 @@ fn prank( new_caller: &Address, new_origin: Option<&Address>, single_call: bool, + delegate_call: bool, ) -> Result { let prank = Prank::new( ccx.caller, @@ -93,8 +134,15 @@ fn prank( new_origin.copied(), ccx.ecx.journaled_state.depth(), single_call, + delegate_call, ); + // Ensure that code exists at `msg.sender` if delegate calling. + if delegate_call { + let code = ccx.code(*new_caller)?; + ensure!(!code.is_empty(), "cannot `prank` delegate call from an EOA"); + } + if let Some(Prank { used, single_call: current_single_call, .. }) = ccx.state.prank { ensure!(used, "cannot overwrite a prank until it is applied at least once"); // This case can only fail if the user calls `vm.startPrank` and then `vm.prank` later on. diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 684f5eb11..046a495a1 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -42,7 +42,7 @@ use proptest::test_runner::{RngAlgorithm, TestRng, TestRunner}; use rand::Rng; use revm::{ interpreter::{ - opcode as op, CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, + opcode as op, CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, EOFCreateInputs, EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterAction, InterpreterResult, }, @@ -941,6 +941,19 @@ where { // Apply our prank if let Some(prank) = &self.prank { + // Apply delegate call, `call.caller`` will not equal `prank.prank_caller` + if let CallScheme::DelegateCall | CallScheme::ExtDelegateCall = call.scheme { + if prank.delegate_call { + call.target_address = prank.new_caller; + call.caller = prank.new_caller; + let acc = ecx.journaled_state.account(prank.new_caller); + call.value = CallValue::Apparent(acc.info.balance); + if let Some(new_origin) = prank.new_origin { + ecx.env.tx.caller = new_origin; + } + } + } + if ecx.journaled_state.depth() >= prank.depth && call.caller == prank.prank_caller { let mut prank_applied = false; diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index d3a377f40..2004c4456 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -353,6 +353,8 @@ interface Vm { function pauseTracing() external view; function prank(address msgSender) external; function prank(address msgSender, address txOrigin) external; + function prank(address msgSender, bool delegateCall) external; + function prank(address msgSender, address txOrigin, bool delegateCall) external; function prevrandao(bytes32 newPrevrandao) external; function prevrandao(uint256 newPrevrandao) external; function projectRoot() external view returns (string memory path); @@ -458,6 +460,8 @@ interface Vm { function startMappingRecording() external; function startPrank(address msgSender) external; function startPrank(address msgSender, address txOrigin) external; + function startPrank(address msgSender, bool delegateCall) external; + function startPrank(address msgSender, address txOrigin, bool delegateCall) external; function startSnapshotGas(string calldata name) external; function startSnapshotGas(string calldata group, string calldata name) external; function startStateDiffRecording() external; diff --git a/testdata/default/cheats/Prank.t.sol b/testdata/default/cheats/Prank.t.sol index d833c0513..130e81960 100644 --- a/testdata/default/cheats/Prank.t.sol +++ b/testdata/default/cheats/Prank.t.sol @@ -85,9 +85,123 @@ contract NestedPranker { } } +contract ImplementationTest { + uint256 public num; + address public sender; + + function assertCorrectCaller(address expectedSender) public { + require(msg.sender == expectedSender); + } + + function assertCorrectOrigin(address expectedOrigin) public { + require(tx.origin == expectedOrigin); + } + + function setNum(uint256 _num) public { + num = _num; + } +} + +contract ProxyTest { + uint256 public num; + address public sender; +} + contract PrankTest is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); + function testPrankDelegateCallPrank2() public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.prank(address(proxy), true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "prank2: delegate call failed assertCorrectCaller"); + + // Assert storage updates + uint256 num = 42; + vm.prank(address(proxy), true); + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successTwo, "prank2: delegate call failed setNum"); + require(proxy.num() == num, "prank2: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testPrankDelegateCallStartPrank2() public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.startPrank(address(proxy), true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "startPrank2: delegate call failed assertCorrectCaller"); + + // Assert storage updates + uint256 num = 42; + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successTwo, "startPrank2: delegate call failed setNum"); + require(proxy.num() == num, "startPrank2: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testPrankDelegateCallPrank3(address origin) public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.prank(address(proxy), origin, true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "prank3: delegate call failed assertCorrectCaller"); + + // Assert correct `tx.origin` + vm.prank(address(proxy), origin, true); + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("assertCorrectOrigin(address)", origin)); + require(successTwo, "prank3: delegate call failed assertCorrectOrigin"); + + // Assert storage updates + uint256 num = 42; + vm.prank(address(proxy), address(origin), true); + (bool successThree,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successThree, "prank3: delegate call failed setNum"); + require(proxy.num() == num, "prank3: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testPrankDelegateCallStartPrank3(address origin) public { + ProxyTest proxy = new ProxyTest(); + ImplementationTest impl = new ImplementationTest(); + vm.startPrank(address(proxy), origin, true); + + // Assert correct `msg.sender` + (bool success,) = + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", address(proxy))); + require(success, "startPrank3: delegate call failed assertCorrectCaller"); + + // Assert correct `tx.origin` + (bool successTwo,) = address(impl).delegatecall(abi.encodeWithSignature("assertCorrectOrigin(address)", origin)); + require(successTwo, "startPrank3: delegate call failed assertCorrectOrigin"); + + // Assert storage updates + uint256 num = 42; + (bool successThree,) = address(impl).delegatecall(abi.encodeWithSignature("setNum(uint256)", num)); + require(successThree, "startPrank3: delegate call failed setNum"); + require(proxy.num() == num, "startPrank3: proxy's storage was not set correctly"); + vm.stopPrank(); + } + + function testFailPrankDelegateCallToEOA() public { + uint256 privateKey = uint256(keccak256(abi.encodePacked("alice"))); + address alice = vm.addr(privateKey); + ImplementationTest impl = new ImplementationTest(); + vm.prank(alice, true); + // Should fail when EOA pranked with delegatecall. + address(impl).delegatecall(abi.encodeWithSignature("assertCorrectCaller(address)", alice)); + } + function testPrankSender(address sender) public { // Perform the prank Victim victim = new Victim(); From 9d7557fcf0f758ea0e8ef5d2db853bd1e1d660dc Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:29:06 +0200 Subject: [PATCH 27/58] feat(forge build): err if no source file in specified paths (#9329) --- crates/forge/bin/cmd/build.rs | 3 +++ crates/forge/tests/cli/cmd.rs | 10 +++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/forge/bin/cmd/build.rs b/crates/forge/bin/cmd/build.rs index f2a1891e2..f803f45f6 100644 --- a/crates/forge/bin/cmd/build.rs +++ b/crates/forge/bin/cmd/build.rs @@ -94,6 +94,9 @@ impl BuildArgs { let path = if joined.exists() { &joined } else { path }; files.extend(source_files_iter(path, MultiCompilerLanguage::FILE_EXTENSIONS)); } + if files.is_empty() { + eyre::bail!("No source files found in specified build paths.") + } } let format_json = shell::is_json(); diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index d4f3973a3..e2e38cc3c 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -2829,7 +2829,7 @@ Compiler run successful! "#]]); // Expect compilation to be skipped as no files have changed - cmd.arg("build").assert_success().stdout_eq(str![[r#" + cmd.forge_fuse().arg("build").assert_success().stdout_eq(str![[r#" No files changed, compilation skipped "#]]); @@ -2952,6 +2952,14 @@ Compiler run successful! [SOLC_VERSION] [ELAPSED] Compiler run successful! +"#]]); + + // Fail if no source file found. + prj.clear(); + cmd.forge_fuse(); + cmd.args(["build", "test/Dummy.sol", "--force"]).assert_failure().stderr_eq(str![[r#" +Error: No source files found in specified build paths. + "#]]); }); From a79dfaed6fc6f88cda5f314a25d1b484d9d8c051 Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:01:01 +0100 Subject: [PATCH 28/58] feat(`forge build`): add `--sizes` and `--names` JSON compatibility (#9321) * add --sizes and --names JSON compatibility + generalize report kind * add additional json output tests * fix feedback nit --- crates/common/Cargo.toml | 2 +- crates/common/src/compile.rs | 91 +++++++++++++++++++++++++------- crates/common/src/lib.rs | 1 + crates/common/src/reports.rs | 19 +++++++ crates/forge/bin/cmd/build.rs | 3 +- crates/forge/bin/cmd/test/mod.rs | 3 +- crates/forge/src/gas_report.rs | 37 ++++++------- crates/forge/tests/cli/build.rs | 45 ++++++++++++++++ crates/forge/tests/cli/cmd.rs | 19 +++++++ 9 files changed, 175 insertions(+), 45 deletions(-) create mode 100644 crates/common/src/reports.rs diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index af95e94bc..8fa745a13 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -54,7 +54,7 @@ num-format.workspace = true reqwest.workspace = true semver.workspace = true serde_json.workspace = true -serde.workspace = true +serde = { workspace = true, features = ["derive"] } thiserror.workspace = true tokio.workspace = true tracing.workspace = true diff --git a/crates/common/src/compile.rs b/crates/common/src/compile.rs index 4c7e7ba0f..507f32830 100644 --- a/crates/common/src/compile.rs +++ b/crates/common/src/compile.rs @@ -1,6 +1,11 @@ //! Support for compiling [foundry_compilers::Project] -use crate::{term::SpinnerReporter, TestFunctionExt}; +use crate::{ + reports::{report_kind, ReportKind}, + shell, + term::SpinnerReporter, + TestFunctionExt, +}; use comfy_table::{presets::ASCII_MARKDOWN, Attribute, Cell, CellAlignment, Color, Table}; use eyre::Result; use foundry_block_explorers::contract::Metadata; @@ -181,11 +186,13 @@ impl ProjectCompiler { } if !quiet { - if output.is_unchanged() { - sh_println!("No files changed, compilation skipped")?; - } else { - // print the compiler output / warnings - sh_println!("{output}")?; + if !shell::is_json() { + if output.is_unchanged() { + sh_println!("No files changed, compilation skipped")?; + } else { + // print the compiler output / warnings + sh_println!("{output}")?; + } } self.handle_output(&output); @@ -205,26 +212,32 @@ impl ProjectCompiler { for (name, (_, version)) in output.versioned_artifacts() { artifacts.entry(version).or_default().push(name); } - for (version, names) in artifacts { - let _ = sh_println!( - " compiler version: {}.{}.{}", - version.major, - version.minor, - version.patch - ); - for name in names { - let _ = sh_println!(" - {name}"); + + if shell::is_json() { + let _ = sh_println!("{}", serde_json::to_string(&artifacts).unwrap()); + } else { + for (version, names) in artifacts { + let _ = sh_println!( + " compiler version: {}.{}.{}", + version.major, + version.minor, + version.patch + ); + for name in names { + let _ = sh_println!(" - {name}"); + } } } } if print_sizes { // add extra newline if names were already printed - if print_names { + if print_names && !shell::is_json() { let _ = sh_println!(); } - let mut size_report = SizeReport { contracts: BTreeMap::new() }; + let mut size_report = + SizeReport { report_kind: report_kind(), contracts: BTreeMap::new() }; let artifacts: BTreeMap<_, _> = output .artifact_ids() @@ -278,6 +291,8 @@ const CONTRACT_INITCODE_SIZE_LIMIT: usize = 49152; /// Contracts with info about their size pub struct SizeReport { + /// What kind of report to generate. + report_kind: ReportKind, /// `contract name -> info` pub contracts: BTreeMap, } @@ -316,6 +331,43 @@ impl SizeReport { impl Display for SizeReport { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + match self.report_kind { + ReportKind::Markdown => { + let table = self.format_table_output(); + writeln!(f, "{table}")?; + } + ReportKind::JSON => { + writeln!(f, "{}", self.format_json_output())?; + } + } + + Ok(()) + } +} + +impl SizeReport { + fn format_json_output(&self) -> String { + let contracts = self + .contracts + .iter() + .filter(|(_, c)| !c.is_dev_contract && (c.runtime_size > 0 || c.init_size > 0)) + .map(|(name, contract)| { + ( + name.clone(), + serde_json::json!({ + "runtime_size": contract.runtime_size, + "init_size": contract.init_size, + "runtime_margin": CONTRACT_RUNTIME_SIZE_LIMIT as isize - contract.runtime_size as isize, + "init_margin": CONTRACT_INITCODE_SIZE_LIMIT as isize - contract.init_size as isize, + }), + ) + }) + .collect::>(); + + serde_json::to_string(&contracts).unwrap() + } + + fn format_table_output(&self) -> Table { let mut table = Table::new(); table.load_preset(ASCII_MARKDOWN); table.set_header([ @@ -366,8 +418,7 @@ impl Display for SizeReport { ]); } - writeln!(f, "{table}")?; - Ok(()) + table } } @@ -476,7 +527,7 @@ pub fn etherscan_project( /// Configures the reporter and runs the given closure. pub fn with_compilation_reporter(quiet: bool, f: impl FnOnce() -> O) -> O { #[allow(clippy::collapsible_else_if)] - let reporter = if quiet { + let reporter = if quiet || shell::is_json() { Report::new(NoReporter::default()) } else { if std::io::stdout().is_terminal() { diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs index 68559d081..259e8fee2 100644 --- a/crates/common/src/lib.rs +++ b/crates/common/src/lib.rs @@ -26,6 +26,7 @@ pub mod errors; pub mod evm; pub mod fs; pub mod provider; +pub mod reports; pub mod retry; pub mod selectors; pub mod serde_helpers; diff --git a/crates/common/src/reports.rs b/crates/common/src/reports.rs new file mode 100644 index 000000000..adbdc11bf --- /dev/null +++ b/crates/common/src/reports.rs @@ -0,0 +1,19 @@ +use serde::{Deserialize, Serialize}; + +use crate::shell; + +#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] +pub enum ReportKind { + #[default] + Markdown, + JSON, +} + +/// Determine the kind of report to generate based on the current shell. +pub fn report_kind() -> ReportKind { + if shell::is_json() { + ReportKind::JSON + } else { + ReportKind::Markdown + } +} diff --git a/crates/forge/bin/cmd/build.rs b/crates/forge/bin/cmd/build.rs index f803f45f6..3efe68db7 100644 --- a/crates/forge/bin/cmd/build.rs +++ b/crates/forge/bin/cmd/build.rs @@ -105,12 +105,11 @@ impl BuildArgs { .print_names(self.names) .print_sizes(self.sizes) .ignore_eip_3860(self.ignore_eip_3860) - .quiet(format_json) .bail(!format_json); let output = compiler.compile(&project)?; - if format_json { + if format_json && !self.names && !self.sizes { sh_println!("{}", serde_json::to_string_pretty(&output.output())?)?; } diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 77ae5d263..613d57078 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -5,7 +5,7 @@ use clap::{Parser, ValueHint}; use eyre::{Context, OptionExt, Result}; use forge::{ decode::decode_console_logs, - gas_report::{GasReport, GasReportKind}, + gas_report::GasReport, multi_runner::matches_contract, result::{SuiteResult, TestOutcome, TestStatus}, traces::{ @@ -583,7 +583,6 @@ impl TestArgs { config.gas_reports.clone(), config.gas_reports_ignore.clone(), config.gas_reports_include_tests, - if shell::is_json() { GasReportKind::JSON } else { GasReportKind::Markdown }, ) }); diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index e3e44994b..7e87af077 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -6,31 +6,23 @@ use crate::{ }; use alloy_primitives::map::HashSet; use comfy_table::{presets::ASCII_MARKDOWN, *}; -use foundry_common::{calc, TestFunctionExt}; +use foundry_common::{ + calc, + reports::{report_kind, ReportKind}, + TestFunctionExt, +}; use foundry_evm::traces::CallKind; use serde::{Deserialize, Serialize}; use serde_json::json; use std::{collections::BTreeMap, fmt::Display}; -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub enum GasReportKind { - Markdown, - JSON, -} - -impl Default for GasReportKind { - fn default() -> Self { - Self::Markdown - } -} - /// Represents the gas report for a set of contracts. #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct GasReport { /// Whether to report any contracts. report_any: bool, /// What kind of report to generate. - report_type: GasReportKind, + report_kind: ReportKind, /// Contracts to generate the report for. report_for: HashSet, /// Contracts to ignore when generating the report. @@ -47,13 +39,18 @@ impl GasReport { report_for: impl IntoIterator, ignore: impl IntoIterator, include_tests: bool, - report_kind: GasReportKind, ) -> Self { let report_for = report_for.into_iter().collect::>(); let ignore = ignore.into_iter().collect::>(); let report_any = report_for.is_empty() || report_for.contains("*"); - let report_type = report_kind; - Self { report_any, report_type, report_for, ignore, include_tests, ..Default::default() } + Self { + report_any, + report_kind: report_kind(), + report_for, + ignore, + include_tests, + ..Default::default() + } } /// Whether the given contract should be reported. @@ -158,8 +155,8 @@ impl GasReport { impl Display for GasReport { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { - match self.report_type { - GasReportKind::Markdown => { + match self.report_kind { + ReportKind::Markdown => { for (name, contract) in &self.contracts { if contract.functions.is_empty() { trace!(name, "gas report contract without functions"); @@ -171,7 +168,7 @@ impl Display for GasReport { writeln!(f, "\n")?; } } - GasReportKind::JSON => { + ReportKind::JSON => { writeln!(f, "{}", &self.format_json_output())?; } } diff --git a/crates/forge/tests/cli/build.rs b/crates/forge/tests/cli/build.rs index 4b257fe8d..dd2545995 100644 --- a/crates/forge/tests/cli/build.rs +++ b/crates/forge/tests/cli/build.rs @@ -82,6 +82,20 @@ forgetest!(initcode_size_exceeds_limit, |prj, cmd| { ... "# ]); + + cmd.forge_fuse().args(["build", "--sizes", "--json"]).assert_failure().stdout_eq( + str![[r#" +{ + "HugeContract":{ + "runtime_size":202, + "init_size":49359, + "runtime_margin":24374, + "init_margin":-207 + } +} +"#]] + .is_json(), + ); }); forgetest!(initcode_size_limit_can_be_ignored, |prj, cmd| { @@ -95,6 +109,23 @@ forgetest!(initcode_size_limit_can_be_ignored, |prj, cmd| { ... "# ]); + + cmd.forge_fuse() + .args(["build", "--sizes", "--ignore-eip-3860", "--json"]) + .assert_success() + .stdout_eq( + str![[r#" +{ + "HugeContract": { + "runtime_size": 202, + "init_size": 49359, + "runtime_margin": 24374, + "init_margin": -207 + } +} +"#]] + .is_json(), + ); }); // tests build output is as expected @@ -118,6 +149,20 @@ forgetest_init!(build_sizes_no_forge_std, |prj, cmd| { ... "# ]); + + cmd.forge_fuse().args(["build", "--sizes", "--json"]).assert_success().stdout_eq( + str![[r#" +{ + "Counter": { + "runtime_size": 247, + "init_size": 277, + "runtime_margin": 24329, + "init_margin": 48875 + } +} +"#]] + .is_json(), + ); }); // tests that skip key in config can be used to skip non-compilable contract diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index e2e38cc3c..1e887791e 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -2977,6 +2977,20 @@ Compiler run successful! "#]]); + + cmd.forge_fuse().args(["build", "--sizes", "--json"]).assert_success().stdout_eq( + str![[r#" +{ + "Counter": { + "runtime_size": 247, + "init_size": 277, + "runtime_margin": 24329, + "init_margin": 48875 + } +} +"#]] + .is_json(), + ); }); // checks that build --names includes all contracts even if unchanged @@ -2992,6 +3006,11 @@ Compiler run successful! ... "#]]); + + cmd.forge_fuse() + .args(["build", "--names", "--json"]) + .assert_success() + .stdout_eq(str![[r#""{...}""#]].is_json()); }); // From 3eb47ea41ba0b26f0c97ce20cad177a43f55d3b5 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Sat, 16 Nov 2024 12:12:14 +0200 Subject: [PATCH 29/58] chore: fix clippy (#9333) --- crates/cast/bin/tx.rs | 2 +- crates/cheatcodes/src/json.rs | 2 +- crates/cheatcodes/src/test/expect.rs | 2 +- crates/common/src/provider/mod.rs | 2 +- crates/evm/core/src/backend/mod.rs | 2 +- crates/evm/core/src/utils.rs | 2 +- crates/evm/coverage/src/anchors.rs | 2 +- crates/fmt/src/comments.rs | 2 +- crates/fmt/src/formatter.rs | 12 ++++++------ crates/forge/bin/cmd/init.rs | 2 +- crates/forge/src/runner.rs | 2 +- crates/script/src/transaction.rs | 2 +- crates/script/src/verify.rs | 2 +- 13 files changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/cast/bin/tx.rs b/crates/cast/bin/tx.rs index a6f64b3db..29f8e2435 100644 --- a/crates/cast/bin/tx.rs +++ b/crates/cast/bin/tx.rs @@ -252,7 +252,7 @@ where }; if self.state.to.is_none() && code.is_none() { - let has_value = self.tx.value.map_or(false, |v| !v.is_zero()); + let has_value = self.tx.value.is_some_and(|v| !v.is_zero()); let has_auth = self.auth.is_some(); // We only allow user to omit the recipient address if transaction is an EIP-7702 tx // without a value. diff --git a/crates/cheatcodes/src/json.rs b/crates/cheatcodes/src/json.rs index 0908f247c..6ad36e474 100644 --- a/crates/cheatcodes/src/json.rs +++ b/crates/cheatcodes/src/json.rs @@ -682,7 +682,7 @@ mod tests { match value { DynSolValue::Tuple(_) | DynSolValue::CustomStruct { .. } => true, DynSolValue::Array(v) | DynSolValue::FixedArray(v) => { - v.first().map_or(false, contains_tuple) + v.first().is_some_and(contains_tuple) } _ => false, } diff --git a/crates/cheatcodes/src/test/expect.rs b/crates/cheatcodes/src/test/expect.rs index 602ac5125..3ee58407a 100644 --- a/crates/cheatcodes/src/test/expect.rs +++ b/crates/cheatcodes/src/test/expect.rs @@ -633,7 +633,7 @@ pub(crate) fn handle_expect_emit( return false } // Maybe match source address. - if event_to_fill_or_check.address.map_or(false, |addr| addr != log.address) { + if event_to_fill_or_check.address.is_some_and(|addr| addr != log.address) { return false; } // Maybe match data. diff --git a/crates/common/src/provider/mod.rs b/crates/common/src/provider/mod.rs index 4fb9e29ae..75efdb869 100644 --- a/crates/common/src/provider/mod.rs +++ b/crates/common/src/provider/mod.rs @@ -137,7 +137,7 @@ impl ProviderBuilder { .wrap_err_with(|| format!("invalid provider URL: {url_str:?}")); // Use the final URL string to guess if it's a local URL. - let is_local = url.as_ref().map_or(false, |url| guess_local_url(url.as_str())); + let is_local = url.as_ref().is_ok_and(|url| guess_local_url(url.as_str())); Self { url, diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index c9bb89047..e70468ef9 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -1972,7 +1972,7 @@ pub fn update_state( persistent_accounts: Option<&HashSet
>, ) -> Result<(), DB::Error> { for (addr, acc) in state.iter_mut() { - if !persistent_accounts.map_or(false, |accounts| accounts.contains(addr)) { + if !persistent_accounts.is_some_and(|accounts| accounts.contains(addr)) { acc.info = db.basic(*addr)?.unwrap_or_default(); for (key, val) in acc.storage.iter_mut() { val.present_value = db.storage(*addr, *key)?; diff --git a/crates/evm/core/src/utils.rs b/crates/evm/core/src/utils.rs index bd17aae44..d76cd087c 100644 --- a/crates/evm/core/src/utils.rs +++ b/crates/evm/core/src/utils.rs @@ -236,7 +236,7 @@ pub fn create2_handler_register( if create2_overrides_inner .borrow() .last() - .map_or(false, |(depth, _)| *depth == ctx.evm.journaled_state.depth()) + .is_some_and(|(depth, _)| *depth == ctx.evm.journaled_state.depth()) { let (_, call_inputs) = create2_overrides_inner.borrow_mut().pop().unwrap(); outcome = ctx.external.call_end(&mut ctx.evm, &call_inputs, outcome); diff --git a/crates/evm/coverage/src/anchors.rs b/crates/evm/coverage/src/anchors.rs index f42fd1a62..6643524d6 100644 --- a/crates/evm/coverage/src/anchors.rs +++ b/crates/evm/coverage/src/anchors.rs @@ -171,7 +171,7 @@ pub fn find_anchor_branch( /// Calculates whether `element` is within the range of the target `location`. fn is_in_source_range(element: &SourceElement, location: &SourceLocation) -> bool { // Source IDs must match. - let source_ids_match = element.index().map_or(false, |a| a as usize == location.source_id); + let source_ids_match = element.index().is_some_and(|a| a as usize == location.source_id); if !source_ids_match { return false; } diff --git a/crates/fmt/src/comments.rs b/crates/fmt/src/comments.rs index 90054f132..e3fb79043 100644 --- a/crates/fmt/src/comments.rs +++ b/crates/fmt/src/comments.rs @@ -112,7 +112,7 @@ impl CommentWithMetadata { // line has something // check if the last comment after code was a postfix comment if last_comment - .map_or(false, |last| last.loc.end() > code_end && !last.is_prefix()) + .is_some_and(|last| last.loc.end() > code_end && !last.is_prefix()) { // get the indent size of the next item of code let next_indent_len = src[comment.loc().end()..] diff --git a/crates/fmt/src/formatter.rs b/crates/fmt/src/formatter.rs index 6bb814e23..8f52d9e25 100644 --- a/crates/fmt/src/formatter.rs +++ b/crates/fmt/src/formatter.rs @@ -88,7 +88,7 @@ struct Context { impl Context { /// Returns true if the current function context is the constructor pub(crate) fn is_constructor_function(&self) -> bool { - self.function.as_ref().map_or(false, |f| matches!(f.ty, FunctionTy::Constructor)) + self.function.as_ref().is_some_and(|f| matches!(f.ty, FunctionTy::Constructor)) } } @@ -341,7 +341,7 @@ impl<'a, W: Write> Formatter<'a, W> { _ => stmt.loc().start(), }; - self.find_next_line(start_from).map_or(false, |loc| loc >= end_at) + self.find_next_line(start_from).is_some_and(|loc| loc >= end_at) } } } @@ -560,7 +560,7 @@ impl<'a, W: Write> Formatter<'a, W> { fn write_doc_block_line(&mut self, comment: &CommentWithMetadata, line: &str) -> Result<()> { if line.trim().starts_with('*') { let line = line.trim().trim_start_matches('*'); - let needs_space = line.chars().next().map_or(false, |ch| !ch.is_whitespace()); + let needs_space = line.chars().next().is_some_and(|ch| !ch.is_whitespace()); write!(self.buf(), " *{}", if needs_space { " " } else { "" })?; self.write_comment_line(comment, line)?; self.write_whitespace_separator(true)?; @@ -1945,7 +1945,7 @@ impl Visitor for Formatter<'_, W> { )?; // EOF newline - if self.last_char().map_or(true, |char| char != '\n') { + if self.last_char() != Some('\n') { writeln!(self.buf())?; } @@ -3259,7 +3259,7 @@ impl Visitor for Formatter<'_, W> { // we can however check if the contract `is` the `base`, this however also does // not cover all cases - let is_contract_base = self.context.contract.as_ref().map_or(false, |contract| { + let is_contract_base = self.context.contract.as_ref().is_some_and(|contract| { contract.base.iter().any(|contract_base| { contract_base .name @@ -3280,7 +3280,7 @@ impl Visitor for Formatter<'_, W> { let mut base_or_modifier = self.visit_to_chunk(loc.start(), Some(loc.end()), base)?; let is_lowercase = - base_or_modifier.content.chars().next().map_or(false, |c| c.is_lowercase()); + base_or_modifier.content.chars().next().is_some_and(|c| c.is_lowercase()); if is_lowercase && base_or_modifier.content.ends_with("()") { base_or_modifier.content.truncate(base_or_modifier.content.len() - 2); } diff --git a/crates/forge/bin/cmd/init.rs b/crates/forge/bin/cmd/init.rs index 82f296e41..472d575bd 100644 --- a/crates/forge/bin/cmd/init.rs +++ b/crates/forge/bin/cmd/init.rs @@ -88,7 +88,7 @@ impl InitArgs { } } else { // if target is not empty - if root.read_dir().map_or(false, |mut i| i.next().is_some()) { + if root.read_dir().is_ok_and(|mut i| i.next().is_some()) { if !force { eyre::bail!( "Cannot run `init` on a non-empty directory.\n\ diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index d0f4f579e..8ed3706de 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -296,7 +296,7 @@ impl ContractRunner<'_> { warnings, ) } - let call_after_invariant = after_invariant_fns.first().map_or(false, |after_invariant_fn| { + let call_after_invariant = after_invariant_fns.first().is_some_and(|after_invariant_fn| { let match_sig = after_invariant_fn.name == "afterInvariant"; if !match_sig { warnings.push(format!( diff --git a/crates/script/src/transaction.rs b/crates/script/src/transaction.rs index fcd4eefc3..ca6a62269 100644 --- a/crates/script/src/transaction.rs +++ b/crates/script/src/transaction.rs @@ -152,7 +152,7 @@ impl ScriptTransactionBuilder { // Add the additional contracts created in this transaction, so we can verify them later. created_contracts.retain(|contract| { // Filter out the contract that was created by the transaction itself. - self.transaction.contract_address.map_or(true, |addr| addr != contract.address) + self.transaction.contract_address != Some(contract.address) }); self.transaction.additional_contracts = created_contracts; diff --git a/crates/script/src/verify.rs b/crates/script/src/verify.rs index c013ee862..55435c559 100644 --- a/crates/script/src/verify.rs +++ b/crates/script/src/verify.rs @@ -116,7 +116,7 @@ impl VerifyBundle { if data.split_at(create2_offset).1.starts_with(bytecode) { let constructor_args = data.split_at(create2_offset + bytecode.len()).1.to_vec(); - if artifact.source.extension().map_or(false, |e| e.to_str() == Some("vy")) { + if artifact.source.extension().is_some_and(|e| e.to_str() == Some("vy")) { warn!("Skipping verification of Vyper contract: {}", artifact.name); } From d14c09f15a9849fe177d097451919810e5877617 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Sat, 16 Nov 2024 13:27:41 +0100 Subject: [PATCH 30/58] test: enhance tests (#9334) * test: enhance tests * update ws url * Assert json unordered * Update crates/test-utils/src/util.rs Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> * Changes after review * Fix rpc url test --------- Co-authored-by: grandizzy Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- crates/cast/tests/cli/main.rs | 9 +++------ crates/test-utils/src/rpc.rs | 5 ++++- crates/test-utils/src/util.rs | 11 ++++++++++- testdata/default/cheats/RpcUrls.t.sol | 2 +- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index bec345b17..a88369e97 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -650,8 +650,7 @@ casttest!(rpc_with_args, |_prj, cmd| { // Call `cast rpc eth_getBlockByNumber 0x123 false` cmd.args(["rpc", "--rpc-url", eth_rpc_url.as_str(), "eth_getBlockByNumber", "0x123", "false"]) - .assert_success() - .stdout_eq(str![[r#" + .assert_json_stdout(str![[r#" {"number":"0x123","hash":"0xc5dab4e189004a1312e9db43a40abb2de91ad7dd25e75880bf36016d8e9df524","transactions":[],"totalDifficulty":"0x4dea420908b","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","nonce":"0x29d6547c196e00e0","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","difficulty":"0x494433b31","gasLimit":"0x1388","gasUsed":"0x0","uncles":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0x3fe6bd17aa85376c7d566df97d9f2e536f37f7a87abb3a6f9e2891cf9442f2e4","mixHash":"0x943056aa305aa6d22a3c06110942980342d1f4d4b11c17711961436a0f963ea0","parentHash":"0x7abfd11e862ccde76d6ea8ee20978aac26f4bcb55de1188cc0335be13e817017","timestamp":"0x55ba4564"} "#]]); @@ -670,8 +669,7 @@ casttest!(rpc_raw_params, |_prj, cmd| { "--raw", r#"["0x123", false]"#, ]) - .assert_success() - .stdout_eq(str![[r#" + .assert_json_stdout(str![[r#" {"number":"0x123","hash":"0xc5dab4e189004a1312e9db43a40abb2de91ad7dd25e75880bf36016d8e9df524","transactions":[],"totalDifficulty":"0x4dea420908b","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","nonce":"0x29d6547c196e00e0","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","difficulty":"0x494433b31","gasLimit":"0x1388","gasUsed":"0x0","uncles":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0x3fe6bd17aa85376c7d566df97d9f2e536f37f7a87abb3a6f9e2891cf9442f2e4","mixHash":"0x943056aa305aa6d22a3c06110942980342d1f4d4b11c17711961436a0f963ea0","parentHash":"0x7abfd11e862ccde76d6ea8ee20978aac26f4bcb55de1188cc0335be13e817017","timestamp":"0x55ba4564"} "#]]); @@ -687,8 +685,7 @@ casttest!(rpc_raw_params_stdin, |_prj, cmd| { stdin.write_all(b"\n[\n\"0x123\",\nfalse\n]\n").unwrap(); }, ) - .assert_success() - .stdout_eq(str![[r#" + .assert_json_stdout(str![[r#" {"number":"0x123","hash":"0xc5dab4e189004a1312e9db43a40abb2de91ad7dd25e75880bf36016d8e9df524","transactions":[],"totalDifficulty":"0x4dea420908b","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","extraData":"0x476574682f4c5649562f76312e302e302f6c696e75782f676f312e342e32","nonce":"0x29d6547c196e00e0","miner":"0xbb7b8287f3f0a933474a79eae42cbca977791171","difficulty":"0x494433b31","gasLimit":"0x1388","gasUsed":"0x0","uncles":[],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x220","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","stateRoot":"0x3fe6bd17aa85376c7d566df97d9f2e536f37f7a87abb3a6f9e2891cf9442f2e4","mixHash":"0x943056aa305aa6d22a3c06110942980342d1f4d4b11c17711961436a0f963ea0","parentHash":"0x7abfd11e862ccde76d6ea8ee20978aac26f4bcb55de1188cc0335be13e817017","timestamp":"0x55ba4564"} "#]]); diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index a974e3954..44deda60c 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -10,6 +10,9 @@ use std::sync::{ // List of general purpose infura keys to rotate through static INFURA_KEYS: LazyLock> = LazyLock::new(|| { let mut keys = vec![ + "6cb19d07ca2d44f59befd61563b1037b", + "6d46c0cca653407b861f3f93f7b0236a", + "69a36846dec146e3a2898429be60be85", // "16a8be88795540b9b3903d8de0f7baa5", // "f4a0bdad42674adab5fc0ac077ffab2b", // "5c812e02193c4ba793f8c214317582bd", @@ -184,7 +187,7 @@ fn next_url(is_ws: bool, chain: NamedChain) -> String { match (is_ws, is_infura) { (false, true) => format!("https://{full}.infura.io/v3/{key}"), - (true, true) => format!("wss://{full}.infura.io/v3/{key}"), + (true, true) => format!("wss://{full}.infura.io/ws/v3/{key}"), (false, false) => format!("https://{full}.g.alchemy.com/v2/{key}"), (true, false) => format!("wss://{full}.g.alchemy.com/v2/{key}"), } diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 5d242800f..8d7f6cbb5 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -11,7 +11,7 @@ use foundry_compilers::{ use foundry_config::Config; use parking_lot::Mutex; use regex::Regex; -use snapbox::{cmd::OutputAssert, str}; +use snapbox::{assert_data_eq, cmd::OutputAssert, str, IntoData}; use std::{ env, ffi::OsStr, @@ -893,6 +893,15 @@ impl TestCommand { self.assert().success() } + /// Runs the command and asserts that it resulted in success, with expected JSON data. + #[track_caller] + pub fn assert_json_stdout(&mut self, expected: impl IntoData) { + let expected = expected.is(snapbox::data::DataFormat::Json).unordered(); + let stdout = self.assert_success().get_output().stdout.clone(); + let actual = stdout.into_data().is(snapbox::data::DataFormat::Json).unordered(); + assert_data_eq!(actual, expected); + } + /// Runs the command and asserts that it **failed** nothing was printed to stdout. #[track_caller] pub fn assert_empty_stdout(&mut self) { diff --git a/testdata/default/cheats/RpcUrls.t.sol b/testdata/default/cheats/RpcUrls.t.sol index 7976fa572..aaa5a00bd 100644 --- a/testdata/default/cheats/RpcUrls.t.sol +++ b/testdata/default/cheats/RpcUrls.t.sol @@ -10,7 +10,7 @@ contract RpcUrlTest is DSTest { // returns the correct url function testCanGetRpcUrl() public { string memory url = vm.rpcUrl("mainnet"); - assertEq(bytes(url).length, 69); + assertTrue(bytes(url).length == 61 || bytes(url).length == 69); } // returns an error if env alias does not exist From e649e62f125244a3ef116be25dfdc81a2afbaf2a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 17 Nov 2024 09:06:44 +0000 Subject: [PATCH 31/58] chore(deps): weekly `cargo update` (#9336) Locking 40 packages to latest compatible versions Updating allocator-api2 v0.2.19 -> v0.2.20 Updating alloy-dyn-abi v0.8.11 -> v0.8.12 Updating alloy-json-abi v0.8.11 -> v0.8.12 Updating alloy-primitives v0.8.11 -> v0.8.12 Updating alloy-sol-macro v0.8.11 -> v0.8.12 Updating alloy-sol-macro-expander v0.8.11 -> v0.8.12 Updating alloy-sol-macro-input v0.8.11 -> v0.8.12 Updating alloy-sol-type-parser v0.8.11 -> v0.8.12 Updating alloy-sol-types v0.8.11 -> v0.8.12 Updating aws-sdk-sts v1.49.0 -> v1.50.0 Updating axum v0.7.7 -> v0.7.9 Updating bstr v1.10.0 -> v1.11.0 Updating cc v1.1.37 -> v1.2.1 Updating clap v4.5.20 -> v4.5.21 Updating clap_builder v4.5.20 -> v4.5.21 Updating clap_complete v4.5.37 -> v4.5.38 Updating clap_lex v0.7.2 -> v0.7.3 Updating comfy-table v7.1.1 -> v7.1.3 Updating cpufeatures v0.2.14 -> v0.2.15 Removing crossterm v0.27.0 Adding diff v0.1.13 Updating flate2 v1.0.34 -> v1.0.35 Updating indicatif v0.17.8 -> v0.17.9 Adding indoc v2.0.5 Updating instability v0.3.2 -> v0.3.3 Removing instant v0.1.13 Updating libc v0.2.162 -> v0.2.164 Adding pretty_assertions v1.4.1 Updating quinn v0.11.5 -> v0.11.6 Updating quinn-proto v0.11.8 -> v0.11.9 Updating regex-automata v0.4.8 -> v0.4.9 Updating rustix v0.38.39 -> v0.38.40 Updating rustls v0.23.16 -> v0.23.17 Updating scc v2.2.4 -> v2.2.5 Updating serde v1.0.214 -> v1.0.215 Updating serde_derive v1.0.214 -> v1.0.215 Updating syn-solidity v0.8.11 -> v0.8.12 Removing thiserror v1.0.68 Adding thiserror v1.0.69 (available: v2.0.3) Adding thiserror v2.0.3 Removing thiserror-impl v1.0.68 Adding thiserror-impl v1.0.69 Adding thiserror-impl v2.0.3 Adding web-time v1.1.0 note: pass `--verbose` to see 44 unchanged dependencies behind latest Co-authored-by: mattsse <19890894+mattsse@users.noreply.github.com> --- Cargo.lock | 416 +++++++++++++++++++++++++++++------------------------ 1 file changed, 228 insertions(+), 188 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af730814c..1922c69b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611cc2ae7d2e242c457e4be7f97036b8ad9ca152b499f53faf99b1ed8fc2553f" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "alloy-chains" @@ -118,14 +118,14 @@ dependencies = [ "alloy-transport", "futures", "futures-util", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "alloy-dyn-abi" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85132f2698b520fab3f54beed55a44389f7006a7b557a0261e1e69439dcc1572" +checksum = "ef2364c782a245cf8725ea6dbfca5f530162702b5d685992ea03ce64529136cc" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -201,9 +201,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded610181f3dad5810f6ff12d1a99994cf9b42d2fcb7709029352398a5da5ae6" +checksum = "b84c506bf264110fa7e90d9924f742f40ef53c6572ea56a0b0bd714a567ed389" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -221,7 +221,7 @@ dependencies = [ "alloy-sol-types", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -243,7 +243,7 @@ dependencies = [ "async-trait", "auto_impl", "futures-utils-wasm", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -261,9 +261,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd58d377699e6cfeab52c4a9d28bdc4ef37e2bd235ff2db525071fe37a2e9af5" +checksum = "9fce5dbd6a4f118eecc4719eaa9c7ffc31c315e6c5ccde3642db927802312425" dependencies = [ "alloy-rlp", "arbitrary", @@ -326,7 +326,7 @@ dependencies = [ "schnellru", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "url", @@ -475,7 +475,7 @@ dependencies = [ "alloy-serde", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -514,7 +514,7 @@ dependencies = [ "auto_impl", "elliptic-curve", "k256", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -531,7 +531,7 @@ dependencies = [ "aws-sdk-kms", "k256", "spki", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -549,7 +549,7 @@ dependencies = [ "gcloud-sdk", "k256", "spki", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -569,7 +569,7 @@ dependencies = [ "coins-ledger", "futures-util", "semver 1.0.23", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -589,7 +589,7 @@ dependencies = [ "eth-keystore", "k256", "rand", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -604,16 +604,16 @@ dependencies = [ "alloy-signer", "async-trait", "semver 1.0.23", - "thiserror", + "thiserror 1.0.69", "tracing", "trezor-client", ] [[package]] name = "alloy-sol-macro" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a1b42ac8f45e2f49f4bcdd72cbfde0bb148f5481d403774ffa546e48b83efc1" +checksum = "9343289b4a7461ed8bab8618504c995c049c082b70c7332efd7b32125633dc05" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -625,9 +625,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06318f1778e57f36333e850aa71bd1bb5e560c10279e236622faae0470c50412" +checksum = "4222d70bec485ceccc5d8fd4f2909edd65b5d5e43d4aca0b5dcee65d519ae98f" dependencies = [ "alloy-json-abi", "alloy-sol-macro-input", @@ -644,9 +644,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaebb9b0ad61a41345a22c9279975c0cdd231b97947b10d7aad1cf0a7181e4a5" +checksum = "2e17f2677369571b976e51ea1430eb41c3690d344fef567b840bfc0b01b6f83a" dependencies = [ "alloy-json-abi", "const-hex", @@ -661,9 +661,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12c71028bfbfec210e24106a542aad3def7caf1a70e2c05710e92a98481980d3" +checksum = "aa64d80ae58ffaafdff9d5d84f58d03775f66c84433916dc9a64ed16af5755da" dependencies = [ "serde", "winnow", @@ -671,9 +671,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d7fb042d68ddfe79ccb23359de3007f6d4d53c13f703b64fb0db422132111" +checksum = "6520d427d4a8eb7aa803d852d7a52ceb0c519e784c292f64bb339e636918cf27" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -694,7 +694,7 @@ dependencies = [ "futures-utils-wasm", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tower 0.5.1", "tracing", @@ -748,7 +748,7 @@ dependencies = [ "alloy-transport", "futures", "http 1.1.0", - "rustls 0.23.16", + "rustls 0.23.17", "serde_json", "tokio", "tokio-tungstenite", @@ -908,7 +908,7 @@ dependencies = [ "serde_repr", "similar-asserts", "tempfile", - "thiserror", + "thiserror 1.0.69", "tikv-jemallocator", "tokio", "tower 0.4.13", @@ -938,7 +938,7 @@ dependencies = [ "revm", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -964,7 +964,7 @@ dependencies = [ "pin-project 1.1.7", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio-util", "tower-http", "tracing", @@ -1394,9 +1394,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53dcf5e7d9bd1517b8b998e170e650047cea8a2b85fe1835abe3210713e541b7" +checksum = "6ada54e5f26ac246dc79727def52f7f8ed38915cb47781e2a72213957dc3a7d5" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1580,9 +1580,9 @@ dependencies = [ [[package]] name = "axum" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", "axum-core", @@ -1797,12 +1797,12 @@ dependencies = [ [[package]] name = "bstr" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" +checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" dependencies = [ "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "serde", ] @@ -1920,7 +1920,7 @@ dependencies = [ "semver 1.0.23", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -1998,9 +1998,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.37" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40545c26d092346d8a8dab71ee48e7685a7a9cba76e634790c215b41a4a7b4cf" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "shlex", ] @@ -2112,9 +2112,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" dependencies = [ "clap_builder", "clap_derive", @@ -2122,9 +2122,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" dependencies = [ "anstream", "anstyle", @@ -2137,9 +2137,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.37" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11611dca53440593f38e6b25ec629de50b14cdfa63adc0fb856115a2c6d97595" +checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" dependencies = [ "clap", ] @@ -2168,9 +2168,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" [[package]] name = "clearscreen" @@ -2180,7 +2180,7 @@ checksum = "2f8c93eb5f77c9050c7750e14f13ef1033a40a0aac70c6371535b6763a01438c" dependencies = [ "nix 0.28.0", "terminfo", - "thiserror", + "thiserror 1.0.69", "which", "winapi", ] @@ -2221,7 +2221,7 @@ dependencies = [ "k256", "serde", "sha2", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2237,7 +2237,7 @@ dependencies = [ "pbkdf2 0.12.2", "rand", "sha2", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2256,7 +2256,7 @@ dependencies = [ "serde", "sha2", "sha3", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2275,7 +2275,7 @@ dependencies = [ "log", "nix 0.26.4", "once_cell", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "wasm-bindgen", @@ -2317,14 +2317,14 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "comfy-table" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" +checksum = "24f165e7b643266ea80cb858aed492ad9280e3e05ce24d4a99d7d7b889b6a4d9" dependencies = [ - "crossterm 0.27.0", + "crossterm", "strum", "strum_macros", - "unicode-width 0.1.14", + "unicode-width 0.2.0", ] [[package]] @@ -2425,9 +2425,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -2475,19 +2475,6 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" -[[package]] -name = "crossterm" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" -dependencies = [ - "bitflags 2.6.0", - "crossterm_winapi", - "libc", - "parking_lot", - "winapi", -] - [[package]] name = "crossterm" version = "0.28.1" @@ -2730,10 +2717,16 @@ dependencies = [ "console", "shell-words", "tempfile", - "thiserror", + "thiserror 1.0.69", "zeroize", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.9.0" @@ -3043,7 +3036,7 @@ dependencies = [ "serde_json", "sha2", "sha3", - "thiserror", + "thiserror 1.0.69", "uuid 0.8.2", ] @@ -3060,7 +3053,7 @@ dependencies = [ "serde", "serde_json", "sha3", - "thiserror", + "thiserror 1.0.69", "uint", ] @@ -3142,7 +3135,7 @@ dependencies = [ "strum", "syn 2.0.87", "tempfile", - "thiserror", + "thiserror 1.0.69", "tiny-keccak", "unicode-xid", ] @@ -3229,7 +3222,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e182f7dbc2ef73d9ef67351c5fbbea084729c48362d3ce9dd44c28e32e277fe5" dependencies = [ "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -3290,9 +3283,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide 0.8.0", @@ -3401,7 +3394,7 @@ dependencies = [ "strum", "svm-rs", "tempfile", - "thiserror", + "thiserror 1.0.69", "tikv-jemallocator", "tokio", "toml 0.8.19", @@ -3434,7 +3427,7 @@ dependencies = [ "serde", "serde_json", "solang-parser", - "thiserror", + "thiserror 1.0.69", "toml 0.8.19", "tracing", ] @@ -3449,7 +3442,7 @@ dependencies = [ "itertools 0.13.0", "similar-asserts", "solang-parser", - "thiserror", + "thiserror 1.0.69", "toml 0.8.19", "tracing", "tracing-subscriber", @@ -3591,7 +3584,7 @@ dependencies = [ "semver 1.0.23", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -3635,7 +3628,7 @@ dependencies = [ "revm-inspectors", "semver 1.0.23", "serde_json", - "thiserror", + "thiserror 1.0.69", "toml 0.8.19", "tracing", "vergen", @@ -3730,7 +3723,7 @@ dependencies = [ "serde_json", "similar-asserts", "terminal_size", - "thiserror", + "thiserror 1.0.69", "tokio", "tower 0.4.13", "tracing", @@ -3790,7 +3783,7 @@ dependencies = [ "svm-rs", "svm-rs-builds", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "winnow", @@ -3824,7 +3817,7 @@ dependencies = [ "serde", "serde_json", "serde_repr", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "walkdir", @@ -3864,7 +3857,7 @@ dependencies = [ "serde_json", "svm-rs", "tempfile", - "thiserror", + "thiserror 1.0.69", "tokio", "walkdir", ] @@ -3897,7 +3890,7 @@ dependencies = [ "similar-asserts", "solang-parser", "tempfile", - "thiserror", + "thiserror 1.0.69", "toml 0.8.19", "toml_edit", "tracing", @@ -3910,7 +3903,7 @@ name = "foundry-debugger" version = "0.2.0" dependencies = [ "alloy-primitives", - "crossterm 0.28.1", + "crossterm", "eyre", "foundry-common", "foundry-compilers", @@ -3946,7 +3939,7 @@ dependencies = [ "revm", "revm-inspectors", "serde", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -3991,7 +3984,7 @@ dependencies = [ "revm-inspectors", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -4033,7 +4026,7 @@ dependencies = [ "rand", "revm", "serde", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -4081,7 +4074,7 @@ dependencies = [ "revm", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "url", @@ -4094,7 +4087,7 @@ dependencies = [ "alloy-primitives", "foundry-compilers", "semver 1.0.23", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4155,7 +4148,7 @@ dependencies = [ "gcloud-sdk", "rpassword", "serde", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -4383,7 +4376,7 @@ dependencies = [ "gix-date", "gix-utils", "itoa", - "thiserror", + "thiserror 1.0.69", "winnow", ] @@ -4403,7 +4396,7 @@ dependencies = [ "memchr", "once_cell", "smallvec", - "thiserror", + "thiserror 1.0.69", "unicode-bom", "winnow", ] @@ -4418,7 +4411,7 @@ dependencies = [ "bstr", "gix-path", "libc", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4430,7 +4423,7 @@ dependencies = [ "bstr", "itoa", "jiff", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4478,7 +4471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93d7df7366121b5018f947a04d37f034717e113dcf9ccd85c34b58e57a74d5e" dependencies = [ "faster-hex", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4489,7 +4482,7 @@ checksum = "e3bc7fe297f1f4614774989c00ec8b1add59571dc9b024b4c00acb7dedd4e19d" dependencies = [ "gix-tempfile", "gix-utils", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4507,7 +4500,7 @@ dependencies = [ "gix-validate", "itoa", "smallvec", - "thiserror", + "thiserror 1.0.69", "winnow", ] @@ -4521,7 +4514,7 @@ dependencies = [ "gix-trace", "home", "once_cell", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4541,7 +4534,7 @@ dependencies = [ "gix-utils", "gix-validate", "memmap2", - "thiserror", + "thiserror 1.0.69", "winnow", ] @@ -4593,7 +4586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e187b263461bc36cea17650141567753bc6207d036cedd1de6e81a52f277ff68" dependencies = [ "bstr", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4611,7 +4604,7 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -4686,7 +4679,7 @@ dependencies = [ "pest_derive", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -4957,7 +4950,7 @@ dependencies = [ "http 1.1.0", "hyper 1.5.0", "hyper-util", - "rustls 0.23.16", + "rustls 0.23.17", "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", @@ -5192,7 +5185,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "same-file", "walkdir", "winapi-util", @@ -5212,7 +5205,7 @@ dependencies = [ "normalize-path", "project-origins", "radix_trie", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", ] @@ -5285,17 +5278,23 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.8" +version = "0.17.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" dependencies = [ "console", - "instant", "number_prefix", "portable-atomic", - "unicode-width 0.1.14", + "unicode-width 0.2.0", + "web-time", ] +[[package]] +name = "indoc" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5" + [[package]] name = "inferno" version = "0.11.21" @@ -5350,23 +5349,18 @@ dependencies = [ [[package]] name = "instability" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c" +checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e" dependencies = [ + "darling", + "indoc", + "pretty_assertions", + "proc-macro2", "quote", "syn 2.0.87", ] -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - [[package]] name = "interprocess" version = "2.2.1" @@ -5578,7 +5572,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" dependencies = [ - "regex-automata 0.4.8", + "regex-automata 0.4.9", ] [[package]] @@ -5592,9 +5586,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.162" +version = "0.2.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18d287de67fe55fd7e1581fe933d965a5a9477b38e949cfa9f8574ef01506398" +checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libdbus-sys" @@ -5802,7 +5796,7 @@ checksum = "d04b0347d2799ef17df4623dbcb03531031142105168e0c549e0bf1f980e9e7e" dependencies = [ "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -5813,7 +5807,7 @@ checksum = "4edc8853320c2a0dab800fbda86253c8938f6ea88510dc92c5f1ed20e794afc1" dependencies = [ "cfg-if", "miette-derive", - "thiserror", + "thiserror 1.0.69", "unicode-width 0.1.14", ] @@ -6527,7 +6521,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879952a81a83930934cbf1786752d6dedc3b1f29e8f8fb2ad1d0a36f377cf442" dependencies = [ "memchr", - "thiserror", + "thiserror 1.0.69", "ucd-trie", ] @@ -6777,6 +6771,16 @@ dependencies = [ "termtree", ] +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettyplease" version = "0.2.25" @@ -6989,7 +6993,7 @@ checksum = "b65f4a8ec18723a734e5dc09c173e0abf9690432da5340285d536edcb4dac190" dependencies = [ "once_cell", "protobuf-support", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -6998,7 +7002,7 @@ version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6872f4d4f4b98303239a2b5838f5bbbb77b01ffc892d627957f37a22d7cfe69c" dependencies = [ - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -7036,7 +7040,7 @@ dependencies = [ "newtype-uuid", "quick-xml 0.36.2", "strip-ansi-escapes", - "thiserror", + "thiserror 1.0.69", "uuid 1.11.0", ] @@ -7069,37 +7073,40 @@ dependencies = [ [[package]] name = "quinn" -version = "0.11.5" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.16", + "rustls 0.23.17", "socket2", - "thiserror", + "thiserror 2.0.3", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom", "rand", "ring", "rustc-hash", - "rustls 0.23.16", + "rustls 0.23.17", + "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.3", "tinyvec", "tracing", + "web-time", ] [[package]] @@ -7190,7 +7197,7 @@ dependencies = [ "bitflags 2.6.0", "cassowary", "compact_str", - "crossterm 0.28.1", + "crossterm", "instability", "itertools 0.13.0", "lru", @@ -7245,7 +7252,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -7256,7 +7263,7 @@ checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.8", + "regex-automata 0.4.9", "regex-syntax 0.8.5", ] @@ -7271,9 +7278,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -7327,7 +7334,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.16", + "rustls 0.23.17", "rustls-native-certs 0.8.0", "rustls-pemfile 2.2.0", "rustls-pki-types", @@ -7380,7 +7387,7 @@ dependencies = [ "revm", "serde", "serde_json", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -7601,9 +7608,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.39" +version = "0.38.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee" +checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0" dependencies = [ "bitflags 2.6.0", "errno", @@ -7626,9 +7633,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "7f1a745511c54ba6d4465e8d5dfbd81b45791756de28d4981af70d6dca128f1e" dependencies = [ "log", "once_cell", @@ -7687,6 +7694,9 @@ name = "rustls-pki-types" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" @@ -7809,9 +7819,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.2.4" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8d25269dd3a12467afe2e510f69fb0b46b698e5afb296b59f2145259deaf8e8" +checksum = "66b202022bb57c049555430e11fc22fea12909276a80a4c3d368da36ac1d88ed" dependencies = [ "sdd", ] @@ -8004,18 +8014,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.215" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", @@ -8266,7 +8276,7 @@ checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ "num-bigint", "num-traits", - "thiserror", + "thiserror 1.0.69", "time", ] @@ -8342,7 +8352,7 @@ dependencies = [ "lalrpop", "lalrpop-util", "phf", - "thiserror", + "thiserror 1.0.69", "unicode-xid", ] @@ -8384,7 +8394,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "thiserror", + "thiserror 1.0.69", "tokio", "toml_edit", "uuid 1.11.0", @@ -8526,7 +8536,7 @@ dependencies = [ "serde_json", "sha2", "tempfile", - "thiserror", + "thiserror 1.0.69", "url", "zip", ] @@ -8568,9 +8578,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf42e81491fb8871b74df3d222c64ae8cbc1269ea509fa768a3ed3e1b0ac8cb" +checksum = "f76fe0a3e1476bdaa0775b9aec5b869ed9520c2b2fedfe9c6df3618f8ea6290b" dependencies = [ "paste", "proc-macro2", @@ -8687,18 +8697,38 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.68" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.3", ] [[package]] name = "thiserror-impl" -version = "1.0.68" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" dependencies = [ "proc-macro2", "quote", @@ -8866,7 +8896,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.16", + "rustls 0.23.17", "rustls-pki-types", "tokio", ] @@ -8879,7 +8909,7 @@ checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" dependencies = [ "either", "futures-util", - "thiserror", + "thiserror 1.0.69", "tokio", ] @@ -8903,7 +8933,7 @@ checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", - "rustls 0.23.16", + "rustls 0.23.17", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -9193,7 +9223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3637e734239e12ab152cd269302500bd063f37624ee210cd04b4936ed671f3b1" dependencies = [ "cc", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -9206,7 +9236,7 @@ dependencies = [ "hex", "protobuf", "rusb", - "thiserror", + "thiserror 1.0.69", "tracing", ] @@ -9229,10 +9259,10 @@ dependencies = [ "httparse", "log", "rand", - "rustls 0.23.16", + "rustls 0.23.17", "rustls-pki-types", "sha1", - "thiserror", + "thiserror 1.0.69", "utf-8", ] @@ -9612,7 +9642,7 @@ dependencies = [ "once_cell", "process-wrap", "project-origins", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "watchexec-events", @@ -9639,7 +9669,7 @@ checksum = "8f7ccc54db7df8cbbe3251508321e46986ce179af4c4a03b4c70bda539d72755" dependencies = [ "miette", "nix 0.28.0", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -9667,6 +9697,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.6" @@ -9716,7 +9756,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -10050,7 +10090,7 @@ dependencies = [ "pharos", "rustc_version 0.4.1", "send_wrapper", - "thiserror", + "thiserror 1.0.69", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", @@ -10202,7 +10242,7 @@ dependencies = [ "flate2", "indexmap 2.6.0", "memchr", - "thiserror", + "thiserror 1.0.69", "zopfli", ] @@ -10213,7 +10253,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25a8c9e90f27d1435088a7b540b6cc8ae6ee525d992a695f16012d2f365b3d3c" dependencies = [ "log", - "thiserror", + "thiserror 1.0.69", "zip", ] From 44c86e76d5e37505cd7349a867e64a845b5b9b2d Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Mon, 18 Nov 2024 08:55:59 +0200 Subject: [PATCH 32/58] chore: fix getArtifactPath flaky test (#9339) --- testdata/default/cheats/GetArtifactPath.t.sol | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/testdata/default/cheats/GetArtifactPath.t.sol b/testdata/default/cheats/GetArtifactPath.t.sol index 538c2e6c9..4b0df4ba6 100644 --- a/testdata/default/cheats/GetArtifactPath.t.sol +++ b/testdata/default/cheats/GetArtifactPath.t.sol @@ -13,25 +13,15 @@ contract GetArtifactPathTest is DSTest { DummyForGetArtifactPath dummy = new DummyForGetArtifactPath(); bytes memory dummyCreationCode = type(DummyForGetArtifactPath).creationCode; - string memory root = vm.projectRoot(); string memory path = vm.getArtifactPathByCode(dummyCreationCode); - - string memory expectedPath = - string.concat(root, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json"); - - assertEq(path, expectedPath); + assertTrue(vm.contains(path, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); } function testGetArtifactPathByDeployedCode() public { DummyForGetArtifactPath dummy = new DummyForGetArtifactPath(); bytes memory dummyRuntimeCode = address(dummy).code; - string memory root = vm.projectRoot(); string memory path = vm.getArtifactPathByDeployedCode(dummyRuntimeCode); - - string memory expectedPath = - string.concat(root, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json"); - - assertEq(path, expectedPath); + assertTrue(vm.contains(path, "/out/default/GetArtifactPath.t.sol/DummyForGetArtifactPath.json")); } } From d275a4901f60a50c5a82fcf10fd5774ddb4598d8 Mon Sep 17 00:00:00 2001 From: Max <82761650+MaxMustermann2@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:18:11 +0530 Subject: [PATCH 33/58] fix(cast storage): respect `--json` for layout (#9332) * feat(cast storage): allow ugly printing of layout Prior to this change, `cast storage $ADDRESS --rpc-url $RPC_URL --etherscan-api-key $ETHERSCAN_API_KEY` always provided a prettified output. This change adds a `--pretty` flag to `cast storage` which defaults to `true` thus retaining backwards compatibility. Passing `--pretty=false` to `cast storage` results in the json output of the storage layout being produced instead. * fix: remove default value from help text The default value is accessible via `cast storage --help` * fix(cast storage): provide output json path * test(cast): add storage_layout_simple_json test * fix(cast storage): use `--json` flag to ugly print * fix(cast storage): include values in json mode * fix(cast-storage): quiet compilation in all cases * chore: cargo clippy * use fixtures, assert JSON * only quiet if JSON mode, avoid unnecessary warning (if you pass an API key you already expect to fetch remote, very likely default) --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: zerosnacks --- crates/cast/bin/cmd/storage.rs | 46 +- crates/cast/tests/cli/main.rs | 33 ++ .../fixtures/storage_layout_complex.json | 397 ++++++++++++++++++ .../tests/fixtures/storage_layout_simple.json | 36 ++ 4 files changed, 503 insertions(+), 9 deletions(-) create mode 100644 crates/cast/tests/fixtures/storage_layout_complex.json create mode 100644 crates/cast/tests/fixtures/storage_layout_simple.json diff --git a/crates/cast/bin/cmd/storage.rs b/crates/cast/bin/cmd/storage.rs index 9fca4172e..5e2459127 100644 --- a/crates/cast/bin/cmd/storage.rs +++ b/crates/cast/bin/cmd/storage.rs @@ -17,6 +17,7 @@ use foundry_common::{ abi::find_source, compile::{etherscan_project, ProjectCompiler}, ens::NameOrAddress, + shell, }; use foundry_compilers::{ artifacts::{ConfigurableContractArtifact, StorageLayout}, @@ -31,6 +32,7 @@ use foundry_config::{ impl_figment_convert_cast, Config, }; use semver::Version; +use serde::{Deserialize, Serialize}; use std::str::FromStr; /// The minimum Solc version for outputting storage layouts. @@ -45,7 +47,7 @@ pub struct StorageArgs { #[arg(value_parser = NameOrAddress::from_str)] address: NameOrAddress, - /// The storage slot number. + /// The storage slot number. If not provided, it gets the full storage layout. #[arg(value_parser = parse_slot)] slot: Option, @@ -109,19 +111,22 @@ impl StorageArgs { if project.paths.has_input_files() { // Find in artifacts and pretty print add_storage_layout_output(&mut project); - let out = ProjectCompiler::new().compile(&project)?; + let out = ProjectCompiler::new().quiet(shell::is_json()).compile(&project)?; let artifact = out.artifacts().find(|(_, artifact)| { artifact.get_deployed_bytecode_bytes().is_some_and(|b| *b == address_code) }); if let Some((_, artifact)) = artifact { - return fetch_and_print_storage(provider, address, block, artifact, true).await; + return fetch_and_print_storage( + provider, + address, + block, + artifact, + !shell::is_json(), + ) + .await; } } - // Not a forge project or artifact not found - // Get code from Etherscan - sh_warn!("No matching artifacts found, fetching source code from Etherscan...")?; - if !self.etherscan.has_key() { eyre::bail!("You must provide an Etherscan API key if you're fetching a remote contract's storage."); } @@ -180,7 +185,7 @@ impl StorageArgs { // Clear temp directory root.close()?; - fetch_and_print_storage(provider, address, block, artifact, true).await + fetch_and_print_storage(provider, address, block, artifact, !shell::is_json()).await } } @@ -215,6 +220,14 @@ impl StorageValue { } } +/// Represents the storage layout of a contract and its values. +#[derive(Clone, Debug, Serialize, Deserialize)] +struct StorageReport { + #[serde(flatten)] + layout: StorageLayout, + values: Vec, +} + async fn fetch_and_print_storage, T: Transport + Clone>( provider: P, address: Address, @@ -255,7 +268,22 @@ async fn fetch_storage_slots, T: Transport + Clone>( fn print_storage(layout: StorageLayout, values: Vec, pretty: bool) -> Result<()> { if !pretty { - sh_println!("{}", serde_json::to_string_pretty(&serde_json::to_value(layout)?)?)?; + let values: Vec<_> = layout + .storage + .iter() + .zip(&values) + .map(|(slot, storage_value)| { + let storage_type = layout.types.get(&slot.storage_type); + storage_value.value( + slot.offset, + storage_type.and_then(|t| t.number_of_bytes.parse::().ok()), + ) + }) + .collect(); + sh_println!( + "{}", + serde_json::to_string_pretty(&serde_json::to_value(StorageReport { layout, values })?)? + )?; return Ok(()) } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index a88369e97..2483fa479 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -1131,6 +1131,23 @@ casttest!(storage_layout_simple, |_prj, cmd| { "#]]); }); +// +casttest!(storage_layout_simple_json, |_prj, cmd| { + cmd.args([ + "storage", + "--rpc-url", + next_rpc_endpoint(NamedChain::Mainnet).as_str(), + "--block", + "21034138", + "--etherscan-api-key", + next_mainnet_etherscan_api_key().as_str(), + "0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2", + "--json", + ]) + .assert_success() + .stdout_eq(file!["../fixtures/storage_layout_simple.json": Json]); +}); + // casttest!(storage_layout_complex, |_prj, cmd| { cmd.args([ @@ -1164,6 +1181,22 @@ casttest!(storage_layout_complex, |_prj, cmd| { "#]]); }); +casttest!(storage_layout_complex_json, |_prj, cmd| { + cmd.args([ + "storage", + "--rpc-url", + next_rpc_endpoint(NamedChain::Mainnet).as_str(), + "--block", + "21034138", + "--etherscan-api-key", + next_mainnet_etherscan_api_key().as_str(), + "0xBA12222222228d8Ba445958a75a0704d566BF2C8", + "--json", + ]) + .assert_success() + .stdout_eq(file!["../fixtures/storage_layout_complex.json": Json]); +}); + casttest!(balance, |_prj, cmd| { let rpc = next_http_rpc_endpoint(); let usdt = "0xdac17f958d2ee523a2206206994597c13d831ec7"; diff --git a/crates/cast/tests/fixtures/storage_layout_complex.json b/crates/cast/tests/fixtures/storage_layout_complex.json new file mode 100644 index 000000000..2cad9dc8c --- /dev/null +++ b/crates/cast/tests/fixtures/storage_layout_complex.json @@ -0,0 +1,397 @@ +{ + "storage": [ + { + "astId": 3805, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_status", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 9499, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_generalPoolsBalances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_struct(IERC20ToBytes32Map)3177_storage)" + }, + { + "astId": 716, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_nextNonce", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 967, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_paused", + "offset": 0, + "slot": "3", + "type": "t_bool" + }, + { + "astId": 8639, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_authorizer", + "offset": 1, + "slot": "3", + "type": "t_contract(IAuthorizer)11086" + }, + { + "astId": 8645, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_approvedRelayers", + "offset": 0, + "slot": "4", + "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" + }, + { + "astId": 5769, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_isPoolRegistered", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_bytes32,t_bool)" + }, + { + "astId": 5771, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_nextPoolNonce", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 9915, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_minimalSwapInfoPoolsBalances", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_bytes32))" + }, + { + "astId": 9919, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_minimalSwapInfoPoolsTokens", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_bytes32,t_struct(AddressSet)3520_storage)" + }, + { + "astId": 10373, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_twoTokenPoolTokens", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_bytes32,t_struct(TwoTokenPoolTokens)10369_storage)" + }, + { + "astId": 4007, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_poolAssetManagers", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_address))" + }, + { + "astId": 8019, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_internalTokenBalance", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_address,t_mapping(t_contract(IERC20)3793,t_uint256))" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32", + "base": "t_address" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(IAuthorizer)11086": { + "encoding": "inplace", + "label": "contract IAuthorizer", + "numberOfBytes": "20" + }, + "t_contract(IERC20)3793": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_bool))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => bool))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_bool)" + }, + "t_mapping(t_address,t_mapping(t_contract(IERC20)3793,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(contract IERC20 => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_contract(IERC20)3793,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_address))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(contract IERC20 => address))", + "numberOfBytes": "32", + "value": "t_mapping(t_contract(IERC20)3793,t_address)" + }, + "t_mapping(t_bytes32,t_mapping(t_contract(IERC20)3793,t_bytes32))": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => mapping(contract IERC20 => bytes32))", + "numberOfBytes": "32", + "value": "t_mapping(t_contract(IERC20)3793,t_bytes32)" + }, + "t_mapping(t_bytes32,t_struct(AddressSet)3520_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct EnumerableSet.AddressSet)", + "numberOfBytes": "32", + "value": "t_struct(AddressSet)3520_storage" + }, + "t_mapping(t_bytes32,t_struct(IERC20ToBytes32Map)3177_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct EnumerableMap.IERC20ToBytes32Map)", + "numberOfBytes": "32", + "value": "t_struct(IERC20ToBytes32Map)3177_storage" + }, + "t_mapping(t_bytes32,t_struct(TwoTokenPoolBalances)10360_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct TwoTokenPoolsBalance.TwoTokenPoolBalances)", + "numberOfBytes": "32", + "value": "t_struct(TwoTokenPoolBalances)10360_storage" + }, + "t_mapping(t_bytes32,t_struct(TwoTokenPoolTokens)10369_storage)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => struct TwoTokenPoolsBalance.TwoTokenPoolTokens)", + "numberOfBytes": "32", + "value": "t_struct(TwoTokenPoolTokens)10369_storage" + }, + "t_mapping(t_contract(IERC20)3793,t_address)": { + "encoding": "mapping", + "key": "t_contract(IERC20)3793", + "label": "mapping(contract IERC20 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_contract(IERC20)3793,t_bytes32)": { + "encoding": "mapping", + "key": "t_contract(IERC20)3793", + "label": "mapping(contract IERC20 => bytes32)", + "numberOfBytes": "32", + "value": "t_bytes32" + }, + "t_mapping(t_contract(IERC20)3793,t_uint256)": { + "encoding": "mapping", + "key": "t_contract(IERC20)3793", + "label": "mapping(contract IERC20 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint256,t_struct(IERC20ToBytes32MapEntry)3166_storage)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => struct EnumerableMap.IERC20ToBytes32MapEntry)", + "numberOfBytes": "32", + "value": "t_struct(IERC20ToBytes32MapEntry)3166_storage" + }, + "t_struct(AddressSet)3520_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "numberOfBytes": "64", + "members": [ + { + "astId": 3515, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 3519, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_uint256)" + } + ] + }, + "t_struct(IERC20ToBytes32Map)3177_storage": { + "encoding": "inplace", + "label": "struct EnumerableMap.IERC20ToBytes32Map", + "numberOfBytes": "96", + "members": [ + { + "astId": 3168, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_length", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 3172, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_entries", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_uint256,t_struct(IERC20ToBytes32MapEntry)3166_storage)" + }, + { + "astId": 3176, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_indexes", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_contract(IERC20)3793,t_uint256)" + } + ] + }, + "t_struct(IERC20ToBytes32MapEntry)3166_storage": { + "encoding": "inplace", + "label": "struct EnumerableMap.IERC20ToBytes32MapEntry", + "numberOfBytes": "64", + "members": [ + { + "astId": 3163, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_key", + "offset": 0, + "slot": "0", + "type": "t_contract(IERC20)3793" + }, + { + "astId": 3165, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "_value", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ] + }, + "t_struct(TwoTokenPoolBalances)10360_storage": { + "encoding": "inplace", + "label": "struct TwoTokenPoolsBalance.TwoTokenPoolBalances", + "numberOfBytes": "64", + "members": [ + { + "astId": 10357, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "sharedCash", + "offset": 0, + "slot": "0", + "type": "t_bytes32" + }, + { + "astId": 10359, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "sharedManaged", + "offset": 0, + "slot": "1", + "type": "t_bytes32" + } + ] + }, + "t_struct(TwoTokenPoolTokens)10369_storage": { + "encoding": "inplace", + "label": "struct TwoTokenPoolsBalance.TwoTokenPoolTokens", + "numberOfBytes": "96", + "members": [ + { + "astId": 10362, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "tokenA", + "offset": 0, + "slot": "0", + "type": "t_contract(IERC20)3793" + }, + { + "astId": 10364, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "tokenB", + "offset": 0, + "slot": "1", + "type": "t_contract(IERC20)3793" + }, + { + "astId": 10368, + "contract": "contracts/vault/Vault.sol:Vault", + "label": "balances", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_struct(TwoTokenPoolBalances)10360_storage)" + } + ] + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + }, + "values": [ + "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000006048a8c631fb7e77eca533cf9c29784e482391e7", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000000000000000000000000000000000000000006e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] +} \ No newline at end of file diff --git a/crates/cast/tests/fixtures/storage_layout_simple.json b/crates/cast/tests/fixtures/storage_layout_simple.json new file mode 100644 index 000000000..35f4777d0 --- /dev/null +++ b/crates/cast/tests/fixtures/storage_layout_simple.json @@ -0,0 +1,36 @@ +{ + "storage": [ + { + "astId": 7, + "contract": "contracts/Create2Deployer.sol:Create2Deployer", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 122, + "contract": "contracts/Create2Deployer.sol:Create2Deployer", + "label": "_paused", + "offset": 20, + "slot": "0", + "type": "t_bool" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + } + }, + "values": [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ] +} \ No newline at end of file From 60dd1d7fe9879008a52da40eb74d5b6706d00b78 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Mon, 18 Nov 2024 18:24:53 +0200 Subject: [PATCH 34/58] feat(`config`): set default evm version to cancun (#9131) * chore: Update to Cancun * cancun to TEST_DATA_DEFAULT, add TEST_DATA_PARIS * Shanghai compat test * Redact gaswaster address --- crates/config/src/lib.rs | 2 +- crates/forge/src/multi_runner.rs | 2 +- crates/forge/tests/cli/build.rs | 6 +- crates/forge/tests/cli/cmd.rs | 462 +++++++++--------- crates/forge/tests/cli/compiler.rs | 2 +- crates/forge/tests/cli/config.rs | 37 ++ crates/forge/tests/cli/ext_integration.rs | 1 + crates/forge/tests/cli/script.rs | 40 +- crates/forge/tests/cli/test_cmd.rs | 86 ++-- crates/forge/tests/it/cheats.rs | 8 +- crates/forge/tests/it/core.rs | 27 +- crates/forge/tests/it/fork.rs | 8 +- crates/forge/tests/it/fuzz.rs | 4 +- crates/forge/tests/it/repros.rs | 5 +- crates/forge/tests/it/spec.rs | 4 +- crates/forge/tests/it/test_helpers.rs | 28 +- .../cheats/BlobBaseFee.t.sol | 0 .../cheats/Blobhashes.t.sol | 0 testdata/default/cheats/Etch.t.sol | 2 +- testdata/default/repros/Issue5929.t.sol | 4 +- testdata/default/repros/Issue6538.t.sol | 4 +- testdata/default/repros/Issue8006.t.sol | 6 +- testdata/paris/cheats/Fork.t.sol | 125 +++++ .../cheats/GasSnapshots.t.sol | 0 .../cheats/LastCallGas.t.sol | 0 .../core/BeforeTest.t.sol} | 2 +- .../{default => paris}/fork/Transact.t.sol | 2 +- testdata/paris/spec/ShanghaiCompat.t.sol | 29 ++ 28 files changed, 555 insertions(+), 341 deletions(-) rename testdata/{cancun => default}/cheats/BlobBaseFee.t.sol (100%) rename testdata/{cancun => default}/cheats/Blobhashes.t.sol (100%) create mode 100644 testdata/paris/cheats/Fork.t.sol rename testdata/{default => paris}/cheats/GasSnapshots.t.sol (100%) rename testdata/{default => paris}/cheats/LastCallGas.t.sol (100%) rename testdata/{default/repros/Issue1543.t.sol => paris/core/BeforeTest.t.sol} (98%) rename testdata/{default => paris}/fork/Transact.t.sol (99%) create mode 100644 testdata/paris/spec/ShanghaiCompat.t.sol diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 986a0181d..b87eadcef 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -2149,7 +2149,7 @@ impl Default for Config { allow_paths: vec![], include_paths: vec![], force: false, - evm_version: EvmVersion::Paris, + evm_version: EvmVersion::Cancun, gas_reports: vec!["*".to_string()], gas_reports_ignore: vec![], gas_reports_include_tests: false, diff --git a/crates/forge/src/multi_runner.rs b/crates/forge/src/multi_runner.rs index e7361db00..a9f2a93eb 100644 --- a/crates/forge/src/multi_runner.rs +++ b/crates/forge/src/multi_runner.rs @@ -449,7 +449,7 @@ impl MultiContractRunnerBuilder { contracts: deployable_contracts, evm_opts, env, - evm_spec: self.evm_spec.unwrap_or(SpecId::MERGE), + evm_spec: self.evm_spec.unwrap_or(SpecId::CANCUN), sender: self.sender, revert_decoder, fork: self.fork, diff --git a/crates/forge/tests/cli/build.rs b/crates/forge/tests/cli/build.rs index dd2545995..51c358612 100644 --- a/crates/forge/tests/cli/build.rs +++ b/crates/forge/tests/cli/build.rs @@ -78,7 +78,7 @@ forgetest!(initcode_size_exceeds_limit, |prj, cmd| { ... | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |--------------|------------------|-------------------|--------------------|---------------------| -| HugeContract | 202 | 49,359 | 24,374 | -207 | +| HugeContract | 194 | 49,344 | 24,382 | -192 | ... "# ]); @@ -105,7 +105,7 @@ forgetest!(initcode_size_limit_can_be_ignored, |prj, cmd| { ... | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |--------------|------------------|-------------------|--------------------|---------------------| -| HugeContract | 202 | 49,359 | 24,374 | -207 | +| HugeContract | 194 | 49,344 | 24,382 | -192 | ... "# ]); @@ -145,7 +145,7 @@ forgetest_init!(build_sizes_no_forge_std, |prj, cmd| { ... | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |----------|------------------|-------------------|--------------------|---------------------| -| Counter | 247 | 277 | 24,329 | 48,875 | +| Counter | 236 | 263 | 24,340 | 48,889 | ... "# ]); diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 1e887791e..18f0327f6 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -1582,25 +1582,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1610,48 +1610,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1666,25 +1666,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1694,48 +1694,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1750,25 +1750,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1778,48 +1778,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1841,25 +1841,25 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1869,48 +1869,48 @@ forgetest!(gas_report_all_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -1932,9 +1932,9 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | ... "#]]); @@ -1944,16 +1944,16 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } } @@ -1970,9 +1970,9 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -1982,16 +1982,16 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -2011,9 +2011,9 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | ... "#]]); @@ -2023,16 +2023,16 @@ forgetest!(gas_report_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } } @@ -2058,17 +2058,17 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]); @@ -2078,32 +2078,32 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -2125,17 +2125,17 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | ... "#]]); @@ -2145,32 +2145,32 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } } @@ -2203,25 +2203,25 @@ forgetest!(gas_report_ignore_some_contracts, |prj, cmd| { | src/Contracts.sol:ContractOne contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101532 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| foo | 45387 | 45387 | 45387 | 45387 | 1 | +| foo | 45370 | 45370 | 45370 | 45370 | 1 | | src/Contracts.sol:ContractThree contract | | | | | | |------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 103591 | 256 | | | | | +| 101748 | 242 | | | | | | Function Name | min | avg | median | max | # calls | -| baz | 260712 | 260712 | 260712 | 260712 | 1 | +| baz | 259210 | 259210 | 259210 | 259210 | 1 | | src/Contracts.sol:ContractTwo contract | | | | | | |----------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 103375 | 255 | | | | | +| 101520 | 241 | | | | | | Function Name | min | avg | median | max | # calls | -| bar | 64984 | 64984 | 64984 | 64984 | 1 | +| bar | 64832 | 64832 | 64832 | 64832 | 1 | ... "#]]) .stderr_eq(str![[r#" @@ -2240,48 +2240,48 @@ Warning: ContractThree is listed in both 'gas_reports' and 'gas_reports_ignore'. { "contract": "src/Contracts.sol:ContractOne", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101532, + "size": 241 }, "functions": { "foo()": { "calls": 1, - "min": 45387, - "mean": 45387, - "median": 45387, - "max": 45387 + "min": 45370, + "mean": 45370, + "median": 45370, + "max": 45370 } } }, { "contract": "src/Contracts.sol:ContractThree", "deployment": { - "gas": 103591, - "size": 256 + "gas": 101748, + "size": 242 }, "functions": { "baz()": { "calls": 1, - "min": 260712, - "mean": 260712, - "median": 260712, - "max": 260712 + "min": 259210, + "mean": 259210, + "median": 259210, + "max": 259210 } } }, { "contract": "src/Contracts.sol:ContractTwo", "deployment": { - "gas": 103375, - "size": 255 + "gas": 101520, + "size": 241 }, "functions": { "bar()": { "calls": 1, - "min": 64984, - "mean": 64984, - "median": 64984, - "max": 64984 + "min": 64832, + "mean": 64832, + "median": 64832, + "max": 64832 } } } @@ -2346,12 +2346,12 @@ contract CounterTest is DSTest { | src/Counter.sol:Counter contract | | | | | | |----------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 101137 | 250 | | | | | +| 99711 | 240 | | | | | | Function Name | min | avg | median | max | # calls | -| a | 2261 | 2261 | 2261 | 2261 | 1 | -| b | 2305 | 2305 | 2305 | 2305 | 1 | -| setNumber(int256) | 23648 | 33604 | 33604 | 43560 | 2 | -| setNumber(uint256) | 23604 | 33560 | 33560 | 43516 | 2 | +| a | 2259 | 2259 | 2259 | 2259 | 1 | +| b | 2304 | 2304 | 2304 | 2304 | 1 | +| setNumber(int256) | 23646 | 33602 | 33602 | 43558 | 2 | +| setNumber(uint256) | 23601 | 33557 | 33557 | 43513 | 2 | ... "#]]); cmd.forge_fuse().arg("test").arg("--gas-report").arg("--json").assert_success().stdout_eq( @@ -2360,37 +2360,37 @@ contract CounterTest is DSTest { { "contract": "src/Counter.sol:Counter", "deployment": { - "gas": 101137, - "size": 250 + "gas": 99711, + "size": 240 }, "functions": { "a()": { "calls": 1, - "min": 2261, - "mean": 2261, - "median": 2261, - "max": 2261 + "min": 2259, + "mean": 2259, + "median": 2259, + "max": 2259 }, "b()": { "calls": 1, - "min": 2305, - "mean": 2305, - "median": 2305, - "max": 2305 + "min": 2304, + "mean": 2304, + "median": 2304, + "max": 2304 }, "setNumber(int256)": { "calls": 2, - "min": 23648, - "mean": 33604, - "median": 33604, - "max": 43560 + "min": 23646, + "mean": 33602, + "median": 33602, + "max": 43558 }, "setNumber(uint256)": { "calls": 2, - "min": 23604, - "mean": 33560, - "median": 33560, - "max": 43516 + "min": 23601, + "mean": 33557, + "median": 33557, + "max": 43513 } } } @@ -2973,7 +2973,7 @@ forgetest_init!(can_build_sizes_repeatedly, |prj, cmd| { Compiler run successful! | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |----------|------------------|-------------------|--------------------|---------------------| -| Counter | 247 | 277 | 24,329 | 48,875 | +| Counter | 236 | 263 | 24,340 | 48,889 | "#]]); @@ -3042,20 +3042,20 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { | src/Counter.sol:Counter contract | | | | | | |----------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 106715 | 277 | | | | | +| 104475 | 263 | | | | | | Function Name | min | avg | median | max | # calls | -| increment | 43404 | 43404 | 43404 | 43404 | 1 | -| number | 283 | 283 | 283 | 283 | 1 | -| setNumber | 23582 | 23582 | 23582 | 23582 | 1 | +| increment | 43401 | 43401 | 43401 | 43401 | 1 | +| number | 281 | 281 | 281 | 281 | 1 | +| setNumber | 23579 | 23579 | 23579 | 23579 | 1 | | test/Counter.t.sol:CounterTest contract | | | | | | |-----------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 965418 | 4661 | | | | | +| 938190 | 4522 | | | | | | Function Name | min | avg | median | max | # calls | -| setUp | 168064 | 168064 | 168064 | 168064 | 1 | -| test_Increment | 52367 | 52367 | 52367 | 52367 | 1 | +| setUp | 165834 | 165834 | 165834 | 165834 | 1 | +| test_Increment | 52357 | 52357 | 52357 | 52357 | 1 | ... "#] @@ -3070,53 +3070,53 @@ forgetest_init!(gas_report_include_tests, |prj, cmd| { { "contract": "src/Counter.sol:Counter", "deployment": { - "gas": 106715, - "size": 277 + "gas": 104475, + "size": 263 }, "functions": { "increment()": { "calls": 1, - "min": 43404, - "mean": 43404, - "median": 43404, - "max": 43404 + "min": 43401, + "mean": 43401, + "median": 43401, + "max": 43401 }, "number()": { "calls": 1, - "min": 283, - "mean": 283, - "median": 283, - "max": 283 + "min": 281, + "mean": 281, + "median": 281, + "max": 281 }, "setNumber(uint256)": { "calls": 1, - "min": 23582, - "mean": 23582, - "median": 23582, - "max": 23582 + "min": 23579, + "mean": 23579, + "median": 23579, + "max": 23579 } } }, { "contract": "test/Counter.t.sol:CounterTest", "deployment": { - "gas": 965418, - "size": 4661 + "gas": 938190, + "size": 4522 }, "functions": { "setUp()": { "calls": 1, - "min": 168064, - "mean": 168064, - "median": 168064, - "max": 168064 + "min": 165834, + "mean": 165834, + "median": 165834, + "max": 165834 }, "test_Increment()": { "calls": 1, - "min": 52367, - "mean": 52367, - "median": 52367, - "max": 52367 + "min": 52357, + "mean": 52357, + "median": 52357, + "max": 52357 } } } diff --git a/crates/forge/tests/cli/compiler.rs b/crates/forge/tests/cli/compiler.rs index b8453b67b..0b58221f2 100644 --- a/crates/forge/tests/cli/compiler.rs +++ b/crates/forge/tests/cli/compiler.rs @@ -242,7 +242,7 @@ Solidity: Vyper: -0.4.0 (<= [..]): +0.4.0 (<= cancun): ├── src/Counter.vy └── src/ICounter.vyi diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index 91e0781af..11bcd49e2 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -776,6 +776,43 @@ forgetest!(normalize_config_evm_version, |_prj, cmd| { .stdout_lossy(); let config: Config = serde_json::from_str(&output).unwrap(); assert_eq!(config.evm_version, EvmVersion::Istanbul); + + // See + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.17", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::London); + + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.18", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::Paris); + + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.23", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::Shanghai); + + let output = cmd + .forge_fuse() + .args(["config", "--use", "0.8.26", "--json"]) + .assert_success() + .get_output() + .stdout_lossy(); + let config: Config = serde_json::from_str(&output).unwrap(); + assert_eq!(config.evm_version, EvmVersion::Cancun); }); // Tests that root paths are properly resolved even if submodule specifies remappings for them. diff --git a/crates/forge/tests/cli/ext_integration.rs b/crates/forge/tests/cli/ext_integration.rs index f0b1c5144..b2747e3cc 100644 --- a/crates/forge/tests/cli/ext_integration.rs +++ b/crates/forge/tests/cli/ext_integration.rs @@ -89,6 +89,7 @@ fn stringutils() { fn lootloose() { ExtTester::new("gakonst", "lootloose", "7b639efe97836155a6a6fc626bf1018d4f8b2495") .install_command(&["make", "install"]) + .args(["--evm-version", "paris"]) .run(); } diff --git a/crates/forge/tests/cli/script.rs b/crates/forge/tests/cli/script.rs index 901ef5922..82c61ccbc 100644 --- a/crates/forge/tests/cli/script.rs +++ b/crates/forge/tests/cli/script.rs @@ -230,7 +230,7 @@ Traces: ├─ [0] VM::startBroadcast() │ └─ ← [Return] ├─ [..] → new GasWaster@[..] - │ └─ ← [Return] 226 bytes of code + │ └─ ← [Return] 221 bytes of code ├─ [..] GasWaster::wasteGas(200000 [2e5]) │ └─ ← [Stop] └─ ← [Stop] @@ -242,10 +242,10 @@ Script ran successfully. ========================== Simulated On-chain Traces: - [45299] → new GasWaster@[..] - └─ ← [Return] 226 bytes of code + [44291] → new GasWaster@[..] + └─ ← [Return] 221 bytes of code - [226] GasWaster::wasteGas(200000 [2e5]) + [224] GasWaster::wasteGas(200000 [2e5]) └─ ← [Stop] @@ -337,7 +337,7 @@ Traces: ├─ [0] VM::startBroadcast() │ └─ ← [Return] ├─ [..] → new GasWaster@[..] - │ └─ ← [Return] 226 bytes of code + │ └─ ← [Return] 221 bytes of code ├─ [..] GasWaster::wasteGas(200000 [2e5]) │ └─ ← [Stop] └─ ← [Stop] @@ -349,10 +349,10 @@ Script ran successfully. ========================== Simulated On-chain Traces: - [45299] → new GasWaster@[..] - └─ ← [Return] 226 bytes of code + [44291] → new GasWaster@[..] + └─ ← [Return] 221 bytes of code - [226] GasWaster::wasteGas(200000 [2e5]) + [224] GasWaster::wasteGas(200000 [2e5]) └─ ← [Stop] @@ -522,7 +522,7 @@ Traces: ├─ [0] VM::startBroadcast() │ └─ ← [Return] ├─ [..] → new HashChecker@[..] - │ └─ ← [Return] 378 bytes of code + │ └─ ← [Return] 368 bytes of code └─ ← [Stop] @@ -2219,15 +2219,15 @@ contract SimpleScript is Script { [SOLC_VERSION] [ELAPSED] Compiler run successful! Traces: - [104553] SimpleScript::run() + [103771] SimpleScript::run() ├─ [0] VM::startBroadcast() │ └─ ← [Return] - ├─ [23875] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 - │ └─ ← [Return] 119 bytes of code - ├─ [13367] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 - │ ├─ [146] A::getValue() [staticcall] + ├─ [23273] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 + │ └─ ← [Return] 116 bytes of code + ├─ [13162] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 + │ ├─ [145] A::getValue() [staticcall] │ │ └─ ← [Return] 100 - │ └─ ← [Return] 63 bytes of code + │ └─ ← [Return] 62 bytes of code └─ ← [Stop] @@ -2237,13 +2237,13 @@ Script ran successfully. ========================== Simulated On-chain Traces: - [23875] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 - └─ ← [Return] 119 bytes of code + [23273] → new A@0x5b73C5498c1E3b4dbA84de0F1833c4a029d90519 + └─ ← [Return] 116 bytes of code - [15867] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 - ├─ [146] A::getValue() [staticcall] + [15662] → new B@0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 + ├─ [145] A::getValue() [staticcall] │ └─ ← [Return] 100 - └─ ← [Return] 63 bytes of code + └─ ← [Return] 62 bytes of code ... "#]]); }); diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 8389c381e..f51cf6703 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -575,7 +575,7 @@ Compiler run successful! Ran 1 test for test/Contract.t.sol:USDTCallingTest [PASS] test() ([GAS]) Traces: - [9516] USDTCallingTest::test() + [9406] USDTCallingTest::test() ├─ [0] VM::createSelectFork("[..]") │ └─ ← [Return] 0 ├─ [3110] 0xdAC17F958D2ee523a2206206994597C13D831ec7::name() [staticcall] @@ -621,12 +621,12 @@ Compiler run successful! Ran 2 tests for test/Contract.t.sol:CustomTypesTest [FAIL: PoolNotInitialized()] testErr() ([GAS]) Traces: - [254] CustomTypesTest::testErr() + [253] CustomTypesTest::testErr() └─ ← [Revert] PoolNotInitialized() [PASS] testEvent() ([GAS]) Traces: - [1268] CustomTypesTest::testEvent() + [1267] CustomTypesTest::testEvent() ├─ emit MyEvent(a: 100) └─ ← [Stop] @@ -996,7 +996,7 @@ Compiler run successful! Ran 1 test for test/Contract.t.sol:PrecompileLabelsTest [PASS] testPrecompileLabels() ([GAS]) Traces: - [9474] PrecompileLabelsTest::testPrecompileLabels() + [9383] PrecompileLabelsTest::testPrecompileLabels() ├─ [0] VM::deal(VM: [0x7109709ECfa91a80626fF3989D68f67F5b1DD12D], 1000000000000000000 [1e18]) │ └─ ← [Return] ├─ [0] VM::deal(console: [0x000000000000000000636F6e736F6c652e6c6f67], 1000000000000000000 [1e18]) @@ -1264,17 +1264,17 @@ Compiler run successful! Ran 1 test for test/Simple.sol:SimpleContractTest [PASS] test() ([GAS]) Traces: - [250463] SimpleContractTest::test() - ├─ [171014] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 854 bytes of code - ├─ [22638] SimpleContract::increment() - │ ├─ [20150] SimpleContract::_setNum(1) + [244864] SimpleContractTest::test() + ├─ [165406] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 826 bytes of code + ├─ [22630] SimpleContract::increment() + │ ├─ [20147] SimpleContract::_setNum(1) │ │ └─ ← 0 │ └─ ← [Stop] - ├─ [23219] SimpleContract::setValues(100, 0x0000000000000000000000000000000000000123) - │ ├─ [250] SimpleContract::_setNum(100) + ├─ [23204] SimpleContract::setValues(100, 0x0000000000000000000000000000000000000123) + │ ├─ [247] SimpleContract::_setNum(100) │ │ └─ ← 1 - │ ├─ [22339] SimpleContract::_setAddr(0x0000000000000000000000000000000000000123) + │ ├─ [22336] SimpleContract::_setAddr(0x0000000000000000000000000000000000000123) │ │ └─ ← 0x0000000000000000000000000000000000000000 │ └─ ← [Stop] └─ ← [Stop] @@ -1326,11 +1326,11 @@ contract SimpleContractTest is Test { r#" ... Traces: - [421947] SimpleContractTest::test() - ├─ [385978] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 1814 bytes of code - ├─ [2534] SimpleContract::setStr("new value") - │ ├─ [1600] SimpleContract::_setStr("new value") + [406629] SimpleContractTest::test() + ├─ [370554] → new SimpleContract@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 1737 bytes of code + ├─ [2511] SimpleContract::setStr("new value") + │ ├─ [1588] SimpleContract::_setStr("new value") │ │ └─ ← "initial value" │ └─ ← [Stop] └─ ← [Stop] @@ -1460,10 +1460,10 @@ contract ATest is Test { cmd.args(["test"]).with_no_redact().assert_success().stdout_eq(str![[r#" ... -[PASS] testNormalGas() (gas: 3202) -[PASS] testWeirdGas1() (gas: 3040) -[PASS] testWeirdGas2() (gas: 3148) -[PASS] testWithAssembly() (gas: 3083) +[PASS] testNormalGas() (gas: 3194) +[PASS] testWeirdGas1() (gas: 3032) +[PASS] testWeirdGas2() (gas: 3139) +[PASS] testWithAssembly() (gas: 3075) ... "#]]); }); @@ -1548,9 +1548,9 @@ contract ATest is Test { cmd.args(["test", "-vvvv"]).with_no_redact().assert_success().stdout_eq(str![[r#" ... Logs: - Gas cost: 34468 + Gas cost: 34367 ... -[PASS] test_GasMeter() (gas: 37512) +[PASS] test_GasMeter() (gas: 37407) ... "#]]); }); @@ -1635,33 +1635,33 @@ contract PauseTracingTest is DSTest { cmd.args(["test", "-vvvvv"]).assert_success().stdout_eq(str![[r#" ... Traces: - [7285] PauseTracingTest::setUp() + [7282] PauseTracingTest::setUp() ├─ emit DummyEvent(i: 1) ├─ [0] VM::pauseTracing() [staticcall] │ └─ ← [Return] └─ ← [Stop] - [294725] PauseTracingTest::test() + [282512] PauseTracingTest::test() ├─ [0] VM::resumeTracing() [staticcall] │ └─ ← [Return] - ├─ [18373] TraceGenerator::generate() - │ ├─ [1280] TraceGenerator::call(0) + ├─ [18327] TraceGenerator::generate() + │ ├─ [1278] TraceGenerator::call(0) │ │ ├─ emit DummyEvent(i: 0) │ │ └─ ← [Stop] - │ ├─ [1280] TraceGenerator::call(1) + │ ├─ [1278] TraceGenerator::call(1) │ │ ├─ emit DummyEvent(i: 1) │ │ └─ ← [Stop] - │ ├─ [1280] TraceGenerator::call(2) + │ ├─ [1278] TraceGenerator::call(2) │ │ ├─ emit DummyEvent(i: 2) │ │ └─ ← [Stop] │ ├─ [0] VM::pauseTracing() [staticcall] │ │ └─ ← [Return] │ ├─ [0] VM::resumeTracing() [staticcall] │ │ └─ ← [Return] - │ ├─ [1280] TraceGenerator::call(8) + │ ├─ [1278] TraceGenerator::call(8) │ │ ├─ emit DummyEvent(i: 8) │ │ └─ ← [Stop] - │ ├─ [1280] TraceGenerator::call(9) + │ ├─ [1278] TraceGenerator::call(9) │ │ ├─ emit DummyEvent(i: 9) │ │ └─ ← [Stop] │ └─ ← [Stop] @@ -2357,11 +2357,11 @@ Compiler run successful! Ran 1 test for test/MetadataTraceTest.t.sol:MetadataTraceTest [PASS] test_proxy_trace() ([GAS]) Traces: - [152142] MetadataTraceTest::test_proxy_trace() - ├─ [49499] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 247 bytes of code - ├─ [37978] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b - │ └─ ← [Return] 63 bytes of code + [149783] MetadataTraceTest::test_proxy_trace() + ├─ [47297] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 236 bytes of code + ├─ [37762] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b + │ └─ ← [Return] 62 bytes of code └─ ← [Stop] Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] @@ -2382,11 +2382,11 @@ Compiler run successful! Ran 1 test for test/MetadataTraceTest.t.sol:MetadataTraceTest [PASS] test_proxy_trace() ([GAS]) Traces: - [130521] MetadataTraceTest::test_proxy_trace() - ├─ [38693] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f - │ └─ ← [Return] 193 bytes of code - ├─ [27175] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b - │ └─ ← [Return] 9 bytes of code + [128142] MetadataTraceTest::test_proxy_trace() + ├─ [36485] → new Counter@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f + │ └─ ← [Return] 182 bytes of code + ├─ [26959] → new Proxy@0x2e234DAe75C793f67A35089C9d99245E1C58470b + │ └─ ← [Return] 8 bytes of code └─ ← [Stop] Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] @@ -2561,7 +2561,7 @@ forgetest_async!(can_get_broadcast_txs, |prj, cmd| { 31337 ); - assertEq(deployedAddress, address(0x030D07c16e2c0a77f74ab16f3C8F10ACeF89FF81)); + assertEq(deployedAddress, address(0x78280279172ED4C0E65BCE5Ee9DFdcd828f837DB)); } function test_getDeployments() public { @@ -2571,7 +2571,7 @@ forgetest_async!(can_get_broadcast_txs, |prj, cmd| { ); assertEq(deployments.length, 2); - assertEq(deployments[0], address(0x030D07c16e2c0a77f74ab16f3C8F10ACeF89FF81)); // Create2 address - latest deployment + assertEq(deployments[0], address(0x78280279172ED4C0E65BCE5Ee9DFdcd828f837DB)); // Create2 address - latest deployment assertEq(deployments[1], address(0x5FbDB2315678afecb367f032d93F642f64180aa3)); // Create address - oldest deployment } diff --git a/crates/forge/tests/it/cheats.rs b/crates/forge/tests/it/cheats.rs index a60602cbc..871cda045 100644 --- a/crates/forge/tests/it/cheats.rs +++ b/crates/forge/tests/it/cheats.rs @@ -3,8 +3,8 @@ use crate::{ config::*, test_helpers::{ - ForgeTestData, RE_PATH_SEPARATOR, TEST_DATA_CANCUN, TEST_DATA_DEFAULT, - TEST_DATA_MULTI_VERSION, + ForgeTestData, RE_PATH_SEPARATOR, TEST_DATA_DEFAULT, TEST_DATA_MULTI_VERSION, + TEST_DATA_PARIS, }, }; use alloy_primitives::U256; @@ -77,6 +77,6 @@ async fn test_cheats_local_multi_version() { } #[tokio::test(flavor = "multi_thread")] -async fn test_cheats_local_cancun() { - test_cheats_local(&TEST_DATA_CANCUN).await +async fn test_cheats_local_paris() { + test_cheats_local(&TEST_DATA_PARIS).await } diff --git a/crates/forge/tests/it/core.rs b/crates/forge/tests/it/core.rs index 17d9f59d8..abab87d28 100644 --- a/crates/forge/tests/it/core.rs +++ b/crates/forge/tests/it/core.rs @@ -1,6 +1,9 @@ //! Forge tests for core functionality. -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; +use crate::{ + config::*, + test_helpers::{TEST_DATA_DEFAULT, TEST_DATA_PARIS}, +}; use forge::result::SuiteResult; use foundry_evm::traces::TraceKind; use foundry_test_utils::Filter; @@ -803,3 +806,25 @@ async fn test_legacy_assertions() { )]), ); } + +/// Test `beforeTest` functionality and `selfdestruct`. +/// See +#[tokio::test(flavor = "multi_thread")] +async fn test_before_setup_with_selfdestruct() { + let filter = Filter::new(".*", ".*BeforeTestSelfDestructTest", ".*"); + let results = TEST_DATA_PARIS.runner().test_collect(&filter); + + assert_multiple( + &results, + BTreeMap::from([( + "paris/core/BeforeTest.t.sol:BeforeTestSelfDestructTest", + vec![ + ("testKill()", true, None, None, None), + ("testA()", true, None, None, None), + ("testSimpleA()", true, None, None, None), + ("testB()", true, None, None, None), + ("testC(uint256)", true, None, None, None), + ], + )]), + ); +} diff --git a/crates/forge/tests/it/fork.rs b/crates/forge/tests/it/fork.rs index 26c45aa18..8dc637528 100644 --- a/crates/forge/tests/it/fork.rs +++ b/crates/forge/tests/it/fork.rs @@ -2,7 +2,7 @@ use crate::{ config::*, - test_helpers::{RE_PATH_SEPARATOR, TEST_DATA_DEFAULT}, + test_helpers::{RE_PATH_SEPARATOR, TEST_DATA_DEFAULT, TEST_DATA_PARIS}, }; use alloy_chains::Chain; use forge::result::SuiteResult; @@ -35,9 +35,9 @@ async fn test_cheats_fork_revert() { /// Executes all non-reverting fork cheatcodes #[tokio::test(flavor = "multi_thread")] async fn test_cheats_fork() { - let mut config = TEST_DATA_DEFAULT.config.clone(); + let mut config = TEST_DATA_PARIS.config.clone(); config.fs_permissions = FsPermissions::new(vec![PathPermission::read("./fixtures")]); - let runner = TEST_DATA_DEFAULT.runner_with_config(config); + let runner = TEST_DATA_PARIS.runner_with_config(config); let filter = Filter::new(".*", ".*", &format!(".*cheats{RE_PATH_SEPARATOR}Fork")) .exclude_tests(".*Revert"); TestConfig::with_filter(runner, filter).run().await; @@ -86,7 +86,7 @@ async fn test_launch_fork_ws() { /// Tests that we can transact transactions in forking mode #[tokio::test(flavor = "multi_thread")] async fn test_transact_fork() { - let runner = TEST_DATA_DEFAULT.runner(); + let runner = TEST_DATA_PARIS.runner(); let filter = Filter::new(".*", ".*", &format!(".*fork{RE_PATH_SEPARATOR}Transact")); TestConfig::with_filter(runner, filter).run().await; } diff --git a/crates/forge/tests/it/fuzz.rs b/crates/forge/tests/it/fuzz.rs index d6b047a17..8972c9bd9 100644 --- a/crates/forge/tests/it/fuzz.rs +++ b/crates/forge/tests/it/fuzz.rs @@ -203,10 +203,10 @@ contract FuzzerDictTest is Test { .unwrap(); // Test that immutable address is used as fuzzed input, causing test to fail. - cmd.args(["test", "--fuzz-seed", "100", "--mt", "testImmutableOwner"]).assert_failure(); + cmd.args(["test", "--fuzz-seed", "119", "--mt", "testImmutableOwner"]).assert_failure(); // Test that storage address is used as fuzzed input, causing test to fail. cmd.forge_fuse() - .args(["test", "--fuzz-seed", "100", "--mt", "testStorageOwner"]) + .args(["test", "--fuzz-seed", "119", "--mt", "testStorageOwner"]) .assert_failure(); }); diff --git a/crates/forge/tests/it/repros.rs b/crates/forge/tests/it/repros.rs index 9f46e3c2e..53185cf97 100644 --- a/crates/forge/tests/it/repros.rs +++ b/crates/forge/tests/it/repros.rs @@ -377,14 +377,11 @@ test_repro!(8383, false, None, |res| { let test = res.test_results.remove("testP256VerifyOutOfBounds()").unwrap(); assert_eq!(test.status, TestStatus::Success); match test.kind { - TestKind::Unit { gas } => assert_eq!(gas, 3103), + TestKind::Unit { gas } => assert_eq!(gas, 3101), _ => panic!("not a unit test kind"), } }); -// https://github.com/foundry-rs/foundry/issues/1543 -test_repro!(1543); - // https://github.com/foundry-rs/foundry/issues/6643 test_repro!(6643); diff --git a/crates/forge/tests/it/spec.rs b/crates/forge/tests/it/spec.rs index db98a15d1..aed2063a0 100644 --- a/crates/forge/tests/it/spec.rs +++ b/crates/forge/tests/it/spec.rs @@ -1,13 +1,13 @@ //! Integration tests for EVM specifications. -use crate::{config::*, test_helpers::TEST_DATA_DEFAULT}; +use crate::{config::*, test_helpers::TEST_DATA_PARIS}; use foundry_evm::revm::primitives::SpecId; use foundry_test_utils::Filter; #[tokio::test(flavor = "multi_thread")] async fn test_shanghai_compat() { let filter = Filter::new("", "ShanghaiCompat", ".*spec"); - TestConfig::with_filter(TEST_DATA_DEFAULT.runner(), filter) + TestConfig::with_filter(TEST_DATA_PARIS.runner(), filter) .evm_spec(SpecId::SHANGHAI) .run() .await; diff --git a/crates/forge/tests/it/test_helpers.rs b/crates/forge/tests/it/test_helpers.rs index eb5a0bf0a..5e540d8c6 100644 --- a/crates/forge/tests/it/test_helpers.rs +++ b/crates/forge/tests/it/test_helpers.rs @@ -34,7 +34,7 @@ static VYPER: LazyLock = LazyLock::new(|| std::env::temp_dir().join("vy /// Profile for the tests group. Used to configure separate configurations for test runs. pub enum ForgeTestProfile { Default, - Cancun, + Paris, MultiVersion, } @@ -42,16 +42,16 @@ impl fmt::Display for ForgeTestProfile { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Default => write!(f, "default"), - Self::Cancun => write!(f, "cancun"), + Self::Paris => write!(f, "paris"), Self::MultiVersion => write!(f, "multi-version"), } } } impl ForgeTestProfile { - /// Returns true if the profile is Cancun. - pub fn is_cancun(&self) -> bool { - matches!(self, Self::Cancun) + /// Returns true if the profile is Paris. + pub fn is_paris(&self) -> bool { + matches!(self, Self::Paris) } pub fn root(&self) -> PathBuf { @@ -66,8 +66,8 @@ impl ForgeTestProfile { let mut settings = Settings { libraries: Libraries::parse(&libs).unwrap(), ..Default::default() }; - if matches!(self, Self::Cancun) { - settings.evm_version = Some(EvmVersion::Cancun); + if matches!(self, Self::Paris) { + settings.evm_version = Some(EvmVersion::Paris); } let settings = SolcConfig::builder().settings(settings).build(); @@ -155,8 +155,8 @@ impl ForgeTestProfile { "fork/Fork.t.sol:DssExecLib:0xfD88CeE74f7D78697775aBDAE53f9Da1559728E4".to_string(), ]; - if self.is_cancun() { - config.evm_version = EvmVersion::Cancun; + if self.is_paris() { + config.evm_version = EvmVersion::Paris; } config @@ -195,8 +195,8 @@ impl ForgeTestData { let mut runner = MultiContractRunnerBuilder::new(Arc::new(self.config.clone())) .sender(self.evm_opts.sender) .with_test_options(self.test_opts.clone()); - if self.profile.is_cancun() { - runner = runner.evm_spec(SpecId::CANCUN); + if self.profile.is_paris() { + runner = runner.evm_spec(SpecId::MERGE); } runner @@ -338,9 +338,9 @@ pub fn get_compiled(project: &mut Project) -> ProjectCompileOutput { pub static TEST_DATA_DEFAULT: LazyLock = LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::Default)); -/// Data for tests requiring Cancun support on Solc and EVM level. -pub static TEST_DATA_CANCUN: LazyLock = - LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::Cancun)); +/// Data for tests requiring Paris support on Solc and EVM level. +pub static TEST_DATA_PARIS: LazyLock = + LazyLock::new(|| ForgeTestData::new(ForgeTestProfile::Paris)); /// Data for tests requiring Cancun support on Solc and EVM level. pub static TEST_DATA_MULTI_VERSION: LazyLock = diff --git a/testdata/cancun/cheats/BlobBaseFee.t.sol b/testdata/default/cheats/BlobBaseFee.t.sol similarity index 100% rename from testdata/cancun/cheats/BlobBaseFee.t.sol rename to testdata/default/cheats/BlobBaseFee.t.sol diff --git a/testdata/cancun/cheats/Blobhashes.t.sol b/testdata/default/cheats/Blobhashes.t.sol similarity index 100% rename from testdata/cancun/cheats/Blobhashes.t.sol rename to testdata/default/cheats/Blobhashes.t.sol diff --git a/testdata/default/cheats/Etch.t.sol b/testdata/default/cheats/Etch.t.sol index 33eaaf44e..f60ea4cad 100644 --- a/testdata/default/cheats/Etch.t.sol +++ b/testdata/default/cheats/Etch.t.sol @@ -8,7 +8,7 @@ contract EtchTest is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function testEtch() public { - address target = address(10); + address target = address(11); bytes memory code = hex"1010"; vm.etch(target, code); assertEq(string(code), string(target.code)); diff --git a/testdata/default/repros/Issue5929.t.sol b/testdata/default/repros/Issue5929.t.sol index 70c5a4f4f..ced9d6d9b 100644 --- a/testdata/default/repros/Issue5929.t.sol +++ b/testdata/default/repros/Issue5929.t.sol @@ -9,8 +9,8 @@ contract Issue5929Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function test_transact_not_working() public { - vm.createSelectFork("mainnet", 15625301); + vm.createSelectFork("mainnet", 21134547); // https://etherscan.io/tx/0x96a129768ec66fd7d65114bf182f4e173bf0b73a44219adaf71f01381a3d0143 - vm.transact(hex"96a129768ec66fd7d65114bf182f4e173bf0b73a44219adaf71f01381a3d0143"); + vm.transact(hex"7dcff74771babf9c23363c4228e55a27f50224d4596b1ba6608b0b45712f94ba"); } } diff --git a/testdata/default/repros/Issue6538.t.sol b/testdata/default/repros/Issue6538.t.sol index 5b318a04c..34c4e2253 100644 --- a/testdata/default/repros/Issue6538.t.sol +++ b/testdata/default/repros/Issue6538.t.sol @@ -9,9 +9,9 @@ contract Issue6538Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); function test_transact() public { - bytes32 lastHash = 0xdbdce1d5c14a6ca17f0e527ab762589d6a73f68697606ae0bb90df7ac9ec5087; + bytes32 lastHash = 0x4b70ca8c5a0990b43df3064372d424d46efa41dfaab961754b86c5afb2df4f61; vm.createSelectFork("mainnet", lastHash); - bytes32 txhash = 0xadbe5cf9269a001d50990d0c29075b402bcc3a0b0f3258821881621b787b35c6; + bytes32 txhash = 0x7dcff74771babf9c23363c4228e55a27f50224d4596b1ba6608b0b45712f94ba; vm.transact(txhash); } } diff --git a/testdata/default/repros/Issue8006.t.sol b/testdata/default/repros/Issue8006.t.sol index 95b16e6f6..efe339d9f 100644 --- a/testdata/default/repros/Issue8006.t.sol +++ b/testdata/default/repros/Issue8006.t.sol @@ -18,10 +18,10 @@ contract Mock { contract Issue8006Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); IERC20 dai; - bytes32 transaction = 0x67cbad73764049e228495a3f90144aab4a37cb4b5fd697dffc234aa5ed811ace; + bytes32 transaction = 0xb23f389b26eb6f95c08e275ec2c360ab3990169492ff0d3e7b7233a3f81d299f; function setUp() public { - vm.createSelectFork("mainnet", 16261704); + vm.createSelectFork("mainnet", 21134541); dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); } @@ -30,7 +30,7 @@ contract Issue8006Test is DSTest { vm.etch(address(dai), address(new Mock()).code); assertEq(dai.totalSupply(), 1); vm.rollFork(transaction); - assertEq(dai.totalSupply(), 5155217627191887307044676292); + assertEq(dai.totalSupply(), 3324657947511778619416491233); } function testRollForkEtchCalled() public { diff --git a/testdata/paris/cheats/Fork.t.sol b/testdata/paris/cheats/Fork.t.sol new file mode 100644 index 000000000..2f2e627de --- /dev/null +++ b/testdata/paris/cheats/Fork.t.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +interface IWETH { + function deposit() external payable; + function balanceOf(address) external view returns (uint256); +} + +contract ForkTest is DSTest { + address constant WETH_TOKEN_ADDR = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; + uint256 constant mainblock = 14_608_400; + + Vm constant vm = Vm(HEVM_ADDRESS); + IWETH WETH = IWETH(WETH_TOKEN_ADDR); + + uint256 forkA; + uint256 forkB; + + uint256 testValue; + + // this will create two _different_ forks during setup + function setUp() public { + forkA = vm.createFork("mainnet", mainblock); + forkB = vm.createFork("mainnet2", mainblock - 1); + testValue = 999; + } + + // ensures forks use different ids + function testForkIdDiffer() public { + assert(forkA != forkB); + } + + // ensures we can create and select in one step + function testCreateSelect() public { + uint256 fork = vm.createSelectFork("mainnet"); + assertEq(fork, vm.activeFork()); + } + + // ensures forks use different ids + function testCanSwitchForks() public { + vm.selectFork(forkA); + vm.selectFork(forkB); + vm.selectFork(forkB); + vm.selectFork(forkA); + } + + function testForksHaveSeparatedStorage() public { + vm.selectFork(forkA); + // read state from forkA + assert(WETH.balanceOf(0x0000000000000000000000000000000000000000) != 1); + + vm.selectFork(forkB); + // read state from forkB + uint256 forkBbalance = WETH.balanceOf(0x0000000000000000000000000000000000000000); + assert(forkBbalance != 1); + + vm.selectFork(forkA); + + // modify state + bytes32 value = bytes32(uint256(1)); + // "0x3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff" is the slot storing the balance of zero address for the weth contract + // `cast index address uint 0x0000000000000000000000000000000000000000 3` + bytes32 zero_address_balance_slot = 0x3617319a054d772f909f7c479a2cebe5066e836a939412e32403c99029b92eff; + vm.store(WETH_TOKEN_ADDR, zero_address_balance_slot, value); + assertEq( + WETH.balanceOf(0x0000000000000000000000000000000000000000), + 1, + "Cheatcode did not change value at the storage slot." + ); + + // switch forks and ensure the balance on forkB remains untouched + vm.selectFork(forkB); + assert(forkBbalance != 1); + // balance of forkB is untouched + assertEq( + WETH.balanceOf(0x0000000000000000000000000000000000000000), + forkBbalance, + "Cheatcode did not change value at the storage slot." + ); + } + + function testCanShareDataAcrossSwaps() public { + assertEq(testValue, 999); + + uint256 val = 300; + vm.selectFork(forkA); + assertEq(val, 300); + + testValue = 100; + + vm.selectFork(forkB); + assertEq(val, 300); + assertEq(testValue, 100); + + val = 99; + testValue = 300; + + vm.selectFork(forkA); + assertEq(val, 99); + assertEq(testValue, 300); + } + + // ensures forks use different ids + function testCanChangeChainId() public { + vm.selectFork(forkA); + uint256 newChainId = 1337; + vm.chainId(newChainId); + uint256 expected = block.chainid; + assertEq(newChainId, expected); + } + + // ensures forks change chain ids automatically + function testCanAutoUpdateChainId() public { + vm.createSelectFork("sepolia"); + assertEq(block.chainid, 11155111); + } + + // ensures forks storage is cached at block + function testStorageCaching() public { + vm.createSelectFork("mainnet", 19800000); + } +} diff --git a/testdata/default/cheats/GasSnapshots.t.sol b/testdata/paris/cheats/GasSnapshots.t.sol similarity index 100% rename from testdata/default/cheats/GasSnapshots.t.sol rename to testdata/paris/cheats/GasSnapshots.t.sol diff --git a/testdata/default/cheats/LastCallGas.t.sol b/testdata/paris/cheats/LastCallGas.t.sol similarity index 100% rename from testdata/default/cheats/LastCallGas.t.sol rename to testdata/paris/cheats/LastCallGas.t.sol diff --git a/testdata/default/repros/Issue1543.t.sol b/testdata/paris/core/BeforeTest.t.sol similarity index 98% rename from testdata/default/repros/Issue1543.t.sol rename to testdata/paris/core/BeforeTest.t.sol index e58f331c4..2b14bcad1 100644 --- a/testdata/default/repros/Issue1543.t.sol +++ b/testdata/paris/core/BeforeTest.t.sol @@ -10,7 +10,7 @@ contract SelfDestructor { } // https://github.com/foundry-rs/foundry/issues/1543 -contract Issue1543Test is DSTest { +contract BeforeTestSelfDestructTest is DSTest { SelfDestructor killer; uint256 a; uint256 b; diff --git a/testdata/default/fork/Transact.t.sol b/testdata/paris/fork/Transact.t.sol similarity index 99% rename from testdata/default/fork/Transact.t.sol rename to testdata/paris/fork/Transact.t.sol index 375658772..92d595f98 100644 --- a/testdata/default/fork/Transact.t.sol +++ b/testdata/paris/fork/Transact.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.18; import "ds-test/test.sol"; import "cheats/Vm.sol"; -import "../logs/console.sol"; +import "../../default/logs/console.sol"; interface IERC20 { function transfer(address to, uint256 amount) external returns (bool); diff --git a/testdata/paris/spec/ShanghaiCompat.t.sol b/testdata/paris/spec/ShanghaiCompat.t.sol new file mode 100644 index 000000000..fd7213b3d --- /dev/null +++ b/testdata/paris/spec/ShanghaiCompat.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +contract ShanghaiCompat is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testPush0() public { + address target = address(uint160(uint256(0xc4f3))); + + bytes memory bytecode = hex"365f5f37365ff3"; + // 36 CALLDATASIZE + // 5F PUSH0 + // 5F PUSH0 + // 37 CALLDATACOPY -> copies calldata at mem[0..calldatasize] + + // 36 CALLDATASIZE + // 5F PUSH0 + // F3 RETURN -> returns mem[0..calldatasize] + + vm.etch(target, bytecode); + + (bool success, bytes memory result) = target.call(bytes("hello PUSH0")); + assertTrue(success); + assertEq(string(result), "hello PUSH0"); + } +} From 550ebd8f473c0f02434ddef9ad9cdca36be4bd54 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:15:25 +0200 Subject: [PATCH 35/58] chore: update test values to cancun (#9344) --- crates/forge/tests/cli/build.rs | 16 ++--- crates/forge/tests/cli/cmd.rs | 110 ++++++++++++++++---------------- 2 files changed, 63 insertions(+), 63 deletions(-) diff --git a/crates/forge/tests/cli/build.rs b/crates/forge/tests/cli/build.rs index 51c358612..9585b216b 100644 --- a/crates/forge/tests/cli/build.rs +++ b/crates/forge/tests/cli/build.rs @@ -87,10 +87,10 @@ forgetest!(initcode_size_exceeds_limit, |prj, cmd| { str![[r#" { "HugeContract":{ - "runtime_size":202, - "init_size":49359, - "runtime_margin":24374, - "init_margin":-207 + "runtime_size":194, + "init_size":49344, + "runtime_margin":24382, + "init_margin":-192 } } "#]] @@ -117,10 +117,10 @@ forgetest!(initcode_size_limit_can_be_ignored, |prj, cmd| { str![[r#" { "HugeContract": { - "runtime_size": 202, - "init_size": 49359, - "runtime_margin": 24374, - "init_margin": -207 + "runtime_size": 194, + "init_size": 49344, + "runtime_margin": 24382, + "init_margin": -192 } } "#]] diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 18f0327f6..3cd4ae5ed 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -2460,16 +2460,16 @@ contract GasReportFallbackTest is Test { Ran 1 test for test/DelegateProxyTest.sol:GasReportFallbackTest [PASS] test_fallback_gas_report() ([GAS]) Traces: - [331067] GasReportFallbackTest::test_fallback_gas_report() - ├─ [106511] → new ProxiedContract@[..] - │ └─ ← [Return] 246 bytes of code - ├─ [108698] → new DelegateProxy@[..] - │ └─ ← [Return] 143 bytes of code - ├─ [29396] DelegateProxy::fallback(100) - │ ├─ [3320] ProxiedContract::deposit(100) [delegatecall] + [327404] GasReportFallbackTest::test_fallback_gas_report() + ├─ [104475] → new ProxiedContract@[..] + │ └─ ← [Return] 236 bytes of code + ├─ [107054] → new DelegateProxy@[..] + │ └─ ← [Return] 135 bytes of code + ├─ [29384] DelegateProxy::fallback(100) + │ ├─ [3316] ProxiedContract::deposit(100) [delegatecall] │ │ └─ ← [Stop] │ └─ ← [Return] - ├─ [21160] DelegateProxy::deposit() + ├─ [21159] DelegateProxy::deposit() │ └─ ← [Stop] └─ ← [Stop] @@ -2477,18 +2477,18 @@ Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] | test/DelegateProxyTest.sol:DelegateProxy contract | | | | | | |---------------------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 108698 | 315 | | | | | +| 107054 | 300 | | | | | | Function Name | min | avg | median | max | # calls | -| deposit | 21160 | 21160 | 21160 | 21160 | 1 | -| fallback | 29396 | 29396 | 29396 | 29396 | 1 | +| deposit | 21159 | 21159 | 21159 | 21159 | 1 | +| fallback | 29384 | 29384 | 29384 | 29384 | 1 | | test/DelegateProxyTest.sol:ProxiedContract contract | | | | | | |-----------------------------------------------------|-----------------|------|--------|------|---------| | Deployment Cost | Deployment Size | | | | | -| 106511 | 276 | | | | | +| 104475 | 263 | | | | | | Function Name | min | avg | median | max | # calls | -| deposit | 3320 | 3320 | 3320 | 3320 | 1 | +| deposit | 3316 | 3316 | 3316 | 3316 | 1 | ... "#]]); @@ -2502,39 +2502,39 @@ Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] { "contract": "test/DelegateProxyTest.sol:DelegateProxy", "deployment": { - "gas": 108698, - "size": 315 + "gas": 107054, + "size": 300 }, "functions": { "deposit()": { "calls": 1, - "min": 21160, - "mean": 21160, - "median": 21160, - "max": 21160 + "min": 21159, + "mean": 21159, + "median": 21159, + "max": 21159 }, "fallback()": { "calls": 1, - "min": 29396, - "mean": 29396, - "median": 29396, - "max": 29396 + "min": 29384, + "mean": 29384, + "median": 29384, + "max": 29384 } } }, { "contract": "test/DelegateProxyTest.sol:ProxiedContract", "deployment": { - "gas": 106511, - "size": 276 + "gas": 104475, + "size": 263 }, "functions": { "deposit(uint256)": { "calls": 1, - "min": 3320, - "mean": 3320, - "median": 3320, - "max": 3320 + "min": 3316, + "mean": 3316, + "median": 3316, + "max": 3316 } } } @@ -2588,25 +2588,25 @@ Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] | test/NestedDeployTest.sol:AnotherChild contract | | | | | | |-------------------------------------------------|-----------------|-------|--------|-------|---------| | Deployment Cost | Deployment Size | | | | | -| 0 | 130 | | | | | +| 0 | 124 | | | | | | Function Name | min | avg | median | max | # calls | -| w | 21162 | 21162 | 21162 | 21162 | 1 | +| w | 21161 | 21161 | 21161 | 21161 | 1 | | test/NestedDeployTest.sol:Child contract | | | | | | |------------------------------------------|-----------------|-----|--------|-----|---------| | Deployment Cost | Deployment Size | | | | | -| 0 | 498 | | | | | +| 0 | 477 | | | | | | Function Name | min | avg | median | max | # calls | -| child | 325 | 325 | 325 | 325 | 1 | +| child | 323 | 323 | 323 | 323 | 1 | | test/NestedDeployTest.sol:Parent contract | | | | | | |-------------------------------------------|-----------------|-----|--------|-----|---------| | Deployment Cost | Deployment Size | | | | | -| 254857 | 770 | | | | | +| 251997 | 739 | | | | | | Function Name | min | avg | median | max | # calls | -| child | 182 | 182 | 182 | 182 | 1 | +| child | 181 | 181 | 181 | 181 | 1 | ... "#]]); @@ -2620,15 +2620,15 @@ Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] "contract": "test/NestedDeployTest.sol:AnotherChild", "deployment": { "gas": 0, - "size": 130 + "size": 124 }, "functions": { "w()": { "calls": 1, - "min": 21162, - "mean": 21162, - "median": 21162, - "max": 21162 + "min": 21161, + "mean": 21161, + "median": 21161, + "max": 21161 } } }, @@ -2636,31 +2636,31 @@ Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] "contract": "test/NestedDeployTest.sol:Child", "deployment": { "gas": 0, - "size": 498 + "size": 477 }, "functions": { "child()": { "calls": 1, - "min": 325, - "mean": 325, - "median": 325, - "max": 325 + "min": 323, + "mean": 323, + "median": 323, + "max": 323 } } }, { "contract": "test/NestedDeployTest.sol:Parent", "deployment": { - "gas": 254857, - "size": 770 + "gas": 251997, + "size": 739 }, "functions": { "child()": { "calls": 1, - "min": 182, - "mean": 182, - "median": 182, - "max": 182 + "min": 181, + "mean": 181, + "median": 181, + "max": 181 } } } @@ -2982,10 +2982,10 @@ Compiler run successful! str![[r#" { "Counter": { - "runtime_size": 247, - "init_size": 277, - "runtime_margin": 24329, - "init_margin": 48875 + "runtime_size": 236, + "init_size": 263, + "runtime_margin": 24340, + "init_margin": 48889 } } "#]] From 7e323c23463193f70c025f0df57b559a79db9676 Mon Sep 17 00:00:00 2001 From: mgiagante <5287175+mgiagante@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:42:38 +0000 Subject: [PATCH 36/58] feat(`forge build -vvvvv`): If verbosity level is 5 or higher show files to compile (#9325) * If verbosity level is 1 or higher, it shows dirty files. * Adds verbose message variant for compilation. * Removing `if..else` statement to always display `self.send_msg`. * Changes order of messages. * Removes semicolons and adds comment on message order. * Removes verbose variant in favor of the already existing variant. * nits, sort the dirty files list and prefix with - * Raises verbosity level to 5+ * Update crates/common/src/term.rs Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --------- Co-authored-by: mgiagante <251503-mgiagante@users.noreply.gitlab.com> Co-authored-by: zerosnacks Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- Cargo.lock | 1 + crates/common/Cargo.toml | 1 + crates/common/src/term.rs | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 1922c69b8..7dc745cbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3716,6 +3716,7 @@ dependencies = [ "foundry-compilers", "foundry-config", "foundry-macros", + "itertools 0.13.0", "num-format", "reqwest", "semver 1.0.23", diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 8fa745a13..033c53e49 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -50,6 +50,7 @@ clap = { version = "4", features = ["derive", "env", "unicode", "wrap_help"] } comfy-table.workspace = true dunce.workspace = true eyre.workspace = true +itertools.workspace = true num-format.workspace = true reqwest.workspace = true semver.workspace = true diff --git a/crates/common/src/term.rs b/crates/common/src/term.rs index ead39b5fa..e67398745 100644 --- a/crates/common/src/term.rs +++ b/crates/common/src/term.rs @@ -3,6 +3,8 @@ use foundry_compilers::{ artifacts::remappings::Remapping, report::{self, BasicStdoutReporter, Reporter}, }; +use foundry_config::find_project_root; +use itertools::Itertools; use semver::Version; use std::{ io, @@ -17,6 +19,8 @@ use std::{ }; use yansi::Paint; +use crate::shell; + /// Some spinners // https://github.com/gernest/wow/blob/master/spin/spinners.go pub static SPINNERS: &[&[&str]] = &[ @@ -151,6 +155,24 @@ impl Drop for SpinnerReporter { impl Reporter for SpinnerReporter { fn on_compiler_spawn(&self, compiler_name: &str, version: &Version, dirty_files: &[PathBuf]) { + // Verbose message with dirty files displays first to avoid being overlapped + // by the spinner in .tick() which prints repeatedly over the same line. + if shell::verbosity() >= 5 { + let project_root = find_project_root(None); + + self.send_msg(format!( + "Files to compile:\n{}", + dirty_files + .iter() + .map(|path| { + let trimmed_path = path.strip_prefix(&project_root).unwrap_or(path); + format!("- {}", trimmed_path.display()) + }) + .sorted() + .format("\n") + )); + } + self.send_msg(format!( "Compiling {} files with {} {}.{}.{}", dirty_files.len(), From 6625e16e57bd66e4f7d43b1d2d6dfb74c4a88469 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:46:06 +0100 Subject: [PATCH 37/58] chore: add some more debugging to forge bind (#9345) --- crates/sol-macro-gen/src/sol_macro_gen.rs | 70 +++++++++++++---------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/crates/sol-macro-gen/src/sol_macro_gen.rs b/crates/sol-macro-gen/src/sol_macro_gen.rs index 7309104fe..8c146aa05 100644 --- a/crates/sol-macro-gen/src/sol_macro_gen.rs +++ b/crates/sol-macro-gen/src/sol_macro_gen.rs @@ -11,7 +11,7 @@ use alloy_sol_macro_expander::expand::expand; use alloy_sol_macro_input::{SolInput, SolInputKind}; -use eyre::{Context, Ok, OptionExt, Result}; +use eyre::{Context, OptionExt, Result}; use foundry_common::fs; use proc_macro2::{Span, TokenStream}; use std::{ @@ -39,7 +39,7 @@ impl SolMacroGen { #path }; - let sol_input: SolInput = syn::parse2(tokens).wrap_err("Failed to parse SolInput {e}")?; + let sol_input: SolInput = syn::parse2(tokens).wrap_err("failed to parse input")?; Ok(sol_input) } @@ -69,24 +69,35 @@ impl MultiSolMacroGen { pub fn generate_bindings(&mut self) -> Result<()> { for instance in &mut self.instances { - let input = instance.get_sol_input()?.normalize_json()?; + Self::generate_binding(instance).wrap_err_with(|| { + format!( + "failed to generate bindings for {}:{}", + instance.path.display(), + instance.name + ) + })?; + } - let SolInput { attrs: _attrs, path: _path, kind } = input; + Ok(()) + } - let tokens = match kind { - SolInputKind::Sol(mut file) => { - let sol_attr: syn::Attribute = syn::parse_quote! { - #[sol(rpc, alloy_sol_types = alloy::sol_types, alloy_contract = alloy::contract)] - }; - file.attrs.push(sol_attr); - expand(file).wrap_err("Failed to expand SolInput")? - } - _ => unreachable!(), - }; + fn generate_binding(instance: &mut SolMacroGen) -> Result<()> { + let input = instance.get_sol_input()?.normalize_json()?; - instance.expansion = Some(tokens); - } + let SolInput { attrs: _, path: _, kind } = input; + let tokens = match kind { + SolInputKind::Sol(mut file) => { + let sol_attr: syn::Attribute = syn::parse_quote! { + #[sol(rpc, alloy_sol_types = alloy::sol_types, alloy_contract = alloy::contract)] + }; + file.attrs.push(sol_attr); + expand(file).wrap_err("failed to expand")? + } + _ => unreachable!(), + }; + + instance.expansion = Some(tokens); Ok(()) } @@ -139,27 +150,28 @@ edition = "2021" )?; // Write src + let parse_error = |name: &str| { + format!("failed to parse generated tokens as an AST for {name};\nthis is likely a bug") + }; for instance in &self.instances { - let name = instance.name.to_lowercase(); - let contents = instance.expansion.as_ref().unwrap().to_string(); + let contents = instance.expansion.as_ref().unwrap(); - if !single_file { - let path = src.join(format!("{name}.rs")); - let file = syn::parse_file(&contents)?; - let contents = prettyplease::unparse(&file); - - fs::write(path.clone(), contents).wrap_err("Failed to write file")?; - writeln!(&mut lib_contents, "pub mod {name};")?; - } else { + let name = instance.name.to_lowercase(); + let path = src.join(format!("{name}.rs")); + let file = syn::parse2(contents.clone()) + .wrap_err_with(|| parse_error(&format!("{}:{}", path.display(), name)))?; + let contents = prettyplease::unparse(&file); + if single_file { write!(&mut lib_contents, "{contents}")?; + } else { + fs::write(path, contents).wrap_err("failed to write to file")?; + writeln!(&mut lib_contents, "pub mod {name};")?; } } let lib_path = src.join("lib.rs"); - let lib_file = syn::parse_file(&lib_contents)?; - + let lib_file = syn::parse_file(&lib_contents).wrap_err_with(|| parse_error("lib.rs"))?; let lib_contents = prettyplease::unparse(&lib_file); - fs::write(lib_path, lib_contents).wrap_err("Failed to write lib.rs")?; Ok(()) From 547d8a52ec7d286214511eb9c8ef5d5be601e81b Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 19 Nov 2024 01:11:59 +0400 Subject: [PATCH 38/58] feat: compilation restrictions (#8668) * [wip] feat: compilation restrictions * Cargo.lock * update patch * fixes * update patch * update patch * wip * deps * bytecode hash * fixes * rm patches * pub --- Cargo.lock | 194 ++++++++++++++++--- Cargo.toml | 4 +- crates/cast/bin/cmd/storage.rs | 4 +- crates/cli/src/utils/cmd.rs | 31 ++- crates/config/src/compilation.rs | 115 +++++++++++ crates/config/src/lib.rs | 76 +++++++- crates/forge/bin/cmd/bind_json.rs | 8 +- crates/forge/bin/cmd/compiler.rs | 8 +- crates/forge/bin/cmd/create.rs | 44 ++++- crates/forge/bin/cmd/eip712.rs | 14 +- crates/forge/bin/cmd/test/mod.rs | 4 +- crates/forge/tests/cli/config.rs | 2 + crates/script/src/verify.rs | 1 + crates/verify/src/etherscan/flatten.rs | 2 +- crates/verify/src/etherscan/standard_json.rs | 9 +- crates/verify/src/provider.rs | 11 +- crates/verify/src/verify.rs | 63 +++++- 17 files changed, 500 insertions(+), 90 deletions(-) create mode 100644 crates/config/src/compilation.rs diff --git a/Cargo.lock b/Cargo.lock index 7dc745cbf..81adf0f4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -799,6 +799,16 @@ dependencies = [ "libc", ] +[[package]] +name = "annotate-snippets" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e35ed54e5ea7997c14ed4c70ba043478db1112e98263b3b035907aa197d991" +dependencies = [ + "anstyle", + "unicode-width 0.1.14", +] + [[package]] name = "anstream" version = "0.6.18" @@ -3572,9 +3582,9 @@ dependencies = [ [[package]] name = "foundry-block-explorers" -version = "0.7.3" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff37530e7c5deead0f9d7dc2a27b070e683bef79735ab453849ebdee74fa848f" +checksum = "0faa449506113b4969029da2ac1df3a1b3201bf10c99a4a8e6d684977b80c938" dependencies = [ "alloy-chains", "alloy-json-abi", @@ -3755,9 +3765,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.11.6" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4754b3f3bb924202b29bd7f0584ea1446018926342884c86029a7d56ef1a22c1" +checksum = "9edf09554357ebfcd2ea28503badbaca311aac3c947d269a6bae5256543aa172" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3780,7 +3790,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "solang-parser", + "solar-parse", "svm-rs", "svm-rs-builds", "tempfile", @@ -3793,9 +3803,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.11.6" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6289da0f17fdb5a0454020dce595502b0abd2a56c15a36d4f6c05bd6c4ff864" +checksum = "134b2499a20136716422f1ae5afd3a5d6c2ef833bf97b7c956285ca96c1d9743" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3803,9 +3813,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.11.6" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf322ab7b726f2bafe9a7e6fb67db02801b35584a2b1d122b4feb52d8e9e7f" +checksum = "78a9be34b3a43e77871e5bbd75f4a81d23eebf8f098519ae1ae9e163a0f3d0da" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3827,9 +3837,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.11.6" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec47f94c7833adfe8049c819d9e31a60c3f440a68cf5baf34c318413d3eb0700" +checksum = "1738950051ebcee2135adac07b3ef1708c6377ffed0c5e9a2bb485f31498befb" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3842,9 +3852,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.11.6" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61971b34545e8ea01502df9d076e811ad3926f27d31adf2641e0c931ca646933" +checksum = "2ac2d9982eedb0eb3819f82c7efa1e28c1f78e031cdfb6adfa34690364fe5e0d" dependencies = [ "alloy-primitives", "cfg-if", @@ -4700,6 +4710,10 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] [[package]] name = "hashbrown" @@ -5255,6 +5269,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" +[[package]] +name = "index_vec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44faf5bb8861a9c72e20d3fb0fdbd59233e43056e2b80475ab0aacdc2e781355" + [[package]] name = "indexmap" version = "1.9.3" @@ -5576,6 +5596,16 @@ dependencies = [ "regex-automata 0.4.9", ] +[[package]] +name = "lasso" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e14eda50a3494b3bf7b9ce51c52434a761e383d7238ce1dd5dcec2fbc13e9fb" +dependencies = [ + "dashmap", + "hashbrown 0.14.5", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -5712,6 +5742,12 @@ dependencies = [ "tendril", ] +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + [[package]] name = "matchers" version = "0.1.0" @@ -5890,9 +5926,9 @@ dependencies = [ [[package]] name = "mockall" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a" +checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2" dependencies = [ "cfg-if", "downcast", @@ -5904,9 +5940,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020" +checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898" dependencies = [ "cfg-if", "proc-macro2", @@ -6383,28 +6419,29 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.12" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +checksum = "8be4817d39f3272f69c59fe05d0535ae6456c2dc2fa1ba02910296c7e0a5c590" dependencies = [ "arrayvec", "bitvec", "byte-slice-cast", "impl-trait-for-tuples", "parity-scale-codec-derive", + "rustversion", "serde", ] [[package]] name = "parity-scale-codec-derive" -version = "3.6.12" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +checksum = "8781a75c6205af67215f382092b6e0a4ff3734798523e69073d4bcd294ec767b" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.87", ] [[package]] @@ -8046,9 +8083,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "indexmap 2.6.0", "itoa", @@ -8357,6 +8394,109 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "solar-ast" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5aeaf7a4bd326242c909bd287291226a540b62b36fa5824880248f4b1d4d6af" +dependencies = [ + "alloy-primitives", + "bumpalo", + "either", + "num-bigint", + "num-rational", + "semver 1.0.23", + "solar-data-structures", + "solar-interface", + "solar-macros", + "strum", + "typed-arena", +] + +[[package]] +name = "solar-config" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31d00d672a40a1a3620d7696f01a2d3301abf883d8168e1a9da3bf83f0c8e343" +dependencies = [ + "strum", +] + +[[package]] +name = "solar-data-structures" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6e4eb0b72ed7adbb808897c85de08ea99609774a58c72e3dce55c758043ca2" +dependencies = [ + "bumpalo", + "index_vec", + "indexmap 2.6.0", + "parking_lot", + "rayon", + "rustc-hash", + "smallvec", +] + +[[package]] +name = "solar-interface" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21fb8925638f3da1bba7a9a6ebeac3511e5c6354f921f2bb2e1ddce4ac70c107" +dependencies = [ + "annotate-snippets", + "anstream", + "anstyle", + "const-hex", + "derive_builder", + "dunce", + "itertools 0.13.0", + "itoa", + "lasso", + "match_cfg", + "normalize-path", + "rayon", + "scc", + "scoped-tls", + "solar-config", + "solar-data-structures", + "solar-macros", + "thiserror 1.0.69", + "tracing", + "unicode-width 0.2.0", +] + +[[package]] +name = "solar-macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0cc54b74e214647c1bbfc098d080cc5deac77f8dcb99aca91747276b01a15ad" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "solar-parse" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82c3659c15975cd80e5e1c44591278c230c59ad89082d797837499a4784e1b" +dependencies = [ + "alloy-primitives", + "bitflags 2.6.0", + "bumpalo", + "itertools 0.13.0", + "memchr", + "num-bigint", + "num-rational", + "num-traits", + "smallvec", + "solar-ast", + "solar-data-structures", + "solar-interface", + "tracing", +] + [[package]] name = "soldeer-commands" version = "0.5.1" @@ -9267,6 +9407,12 @@ dependencies = [ "utf-8", ] +[[package]] +name = "typed-arena" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6af6ae20167a9ece4bcb41af5b80f8a1f1df981f6391189ce00fd257af04126a" + [[package]] name = "typenum" version = "1.17.0" diff --git a/Cargo.toml b/Cargo.toml index 0c0962a2d..624264cf2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -168,8 +168,8 @@ foundry-wallets = { path = "crates/wallets" } foundry-linking = { path = "crates/linking" } # solc & compilation utilities -foundry-block-explorers = { version = "0.7.3", default-features = false } -foundry-compilers = { version = "0.11.6", default-features = false } +foundry-block-explorers = { version = "0.9.0", default-features = false } +foundry-compilers = { version = "0.12.1", default-features = false } foundry-fork-db = "0.6.0" solang-parser = "=0.3.3" diff --git a/crates/cast/bin/cmd/storage.rs b/crates/cast/bin/cmd/storage.rs index 5e2459127..13fa908bc 100644 --- a/crates/cast/bin/cmd/storage.rs +++ b/crates/cast/bin/cmd/storage.rs @@ -23,7 +23,7 @@ use foundry_compilers::{ artifacts::{ConfigurableContractArtifact, StorageLayout}, compilers::{ solc::{Solc, SolcCompiler}, - Compiler, CompilerSettings, + Compiler, }, Artifact, Project, }; @@ -316,7 +316,7 @@ fn print_storage(layout: StorageLayout, values: Vec, pretty: bool) fn add_storage_layout_output(project: &mut Project) { project.artifacts.additional_values.storage_layout = true; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { selection.0.values_mut().for_each(|contract_selection| { contract_selection .values_mut() diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 2ebdc2539..19e4425b5 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -3,10 +3,10 @@ use alloy_primitives::Address; use eyre::{Result, WrapErr}; use foundry_common::{fs, TestFunctionExt}; use foundry_compilers::{ - artifacts::{CompactBytecode, CompactDeployedBytecode, Settings}, + artifacts::{CompactBytecode, Settings}, cache::{CacheEntry, CompilerCache}, utils::read_json_file, - Artifact, ProjectCompileOutput, + Artifact, ArtifactId, ProjectCompileOutput, }; use foundry_config::{error::ExtractConfigError, figment::Figment, Chain, Config, NamedChain}; use foundry_debugger::Debugger; @@ -32,17 +32,21 @@ use yansi::Paint; /// Runtime Bytecode of the given contract. #[track_caller] pub fn remove_contract( - output: &mut ProjectCompileOutput, + output: ProjectCompileOutput, path: &Path, name: &str, -) -> Result<(JsonAbi, CompactBytecode, CompactDeployedBytecode)> { - let contract = if let Some(contract) = output.remove(path, name) { - contract - } else { +) -> Result<(JsonAbi, CompactBytecode, ArtifactId)> { + let mut other = Vec::new(); + let Some((id, contract)) = output.into_artifacts().find_map(|(id, artifact)| { + if id.name == name && id.source == path { + Some((id, artifact)) + } else { + other.push(id.name); + None + } + }) else { let mut err = format!("could not find artifact: `{name}`"); - if let Some(suggestion) = - super::did_you_mean(name, output.artifacts().map(|(name, _)| name)).pop() - { + if let Some(suggestion) = super::did_you_mean(name, other).pop() { if suggestion != name { err = format!( r#"{err} @@ -64,12 +68,7 @@ pub fn remove_contract( .ok_or_else(|| eyre::eyre!("contract {} does not contain bytecode", name))? .into_owned(); - let runtime = contract - .get_deployed_bytecode() - .ok_or_else(|| eyre::eyre!("contract {} does not contain deployed bytecode", name))? - .into_owned(); - - Ok((abi, bin, runtime)) + Ok((abi, bin, id)) } /// Helper function for finding a contract by ContractName diff --git a/crates/config/src/compilation.rs b/crates/config/src/compilation.rs new file mode 100644 index 000000000..b4f00b91b --- /dev/null +++ b/crates/config/src/compilation.rs @@ -0,0 +1,115 @@ +use crate::{filter::GlobMatcher, serde_helpers}; +use foundry_compilers::{ + artifacts::{BytecodeHash, EvmVersion}, + multi::{MultiCompilerRestrictions, MultiCompilerSettings}, + settings::VyperRestrictions, + solc::{Restriction, SolcRestrictions}, + RestrictionsWithVersion, +}; +use semver::VersionReq; +use serde::{Deserialize, Serialize}; + +/// Keeps possible overrides for default settings which users may configure to construct additional +/// settings profile. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct SettingsOverrides { + pub name: String, + pub via_ir: Option, + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub evm_version: Option, + pub optimizer: Option, + pub optimizer_runs: Option, + pub bytecode_hash: Option, +} + +impl SettingsOverrides { + /// Applies the overrides to the given settings. + pub fn apply(&self, settings: &mut MultiCompilerSettings) { + if let Some(via_ir) = self.via_ir { + settings.solc.via_ir = Some(via_ir); + } + + if let Some(evm_version) = self.evm_version { + settings.solc.evm_version = Some(evm_version); + settings.vyper.evm_version = Some(evm_version); + } + + if let Some(enabled) = self.optimizer { + settings.solc.optimizer.enabled = Some(enabled); + } + + if let Some(optimizer_runs) = self.optimizer_runs { + settings.solc.optimizer.runs = Some(optimizer_runs); + } + + if let Some(bytecode_hash) = self.bytecode_hash { + if let Some(metadata) = settings.solc.metadata.as_mut() { + metadata.bytecode_hash = Some(bytecode_hash); + } else { + settings.solc.metadata = Some(bytecode_hash.into()); + } + } + } +} + +#[derive(Debug, thiserror::Error)] +pub enum RestrictionsError { + #[error("specified both exact and relative restrictions for {0}")] + BothExactAndRelative(&'static str), +} + +/// Restrictions for compilation of given paths. +/// +/// Only purpose of this type is to accept user input to later construct +/// `RestrictionsWithVersion`. +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] +pub struct CompilationRestrictions { + pub paths: GlobMatcher, + pub version: Option, + pub via_ir: Option, + pub bytecode_hash: Option, + + pub min_optimizer_runs: Option, + pub optimizer_runs: Option, + pub max_optimizer_runs: Option, + + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub min_evm_version: Option, + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub evm_version: Option, + #[serde(default, with = "serde_helpers::display_from_str_opt")] + pub max_evm_version: Option, +} + +impl TryFrom for RestrictionsWithVersion { + type Error = RestrictionsError; + + fn try_from(value: CompilationRestrictions) -> Result { + let (min_evm, max_evm) = + match (value.min_evm_version, value.max_evm_version, value.evm_version) { + (None, None, Some(exact)) => (Some(exact), Some(exact)), + (min, max, None) => (min, max), + _ => return Err(RestrictionsError::BothExactAndRelative("evm_version")), + }; + let (min_opt, max_opt) = + match (value.min_optimizer_runs, value.max_optimizer_runs, value.optimizer_runs) { + (None, None, Some(exact)) => (Some(exact), Some(exact)), + (min, max, None) => (min, max), + _ => return Err(RestrictionsError::BothExactAndRelative("optimizer_runs")), + }; + Ok(Self { + restrictions: MultiCompilerRestrictions { + solc: SolcRestrictions { + evm_version: Restriction { min: min_evm, max: max_evm }, + via_ir: value.via_ir, + optimizer_runs: Restriction { min: min_opt, max: max_opt }, + bytecode_hash: value.bytecode_hash, + }, + vyper: VyperRestrictions { + evm_version: Restriction { min: min_evm, max: max_evm }, + }, + }, + version: value.version, + }) + } +} diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index b87eadcef..6444802e3 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -33,8 +33,10 @@ use foundry_compilers::{ Compiler, }, error::SolcError, + multi::{MultiCompilerParsedSource, MultiCompilerRestrictions}, solc::{CliSettings, SolcSettings}, - ConfigurableArtifacts, Project, ProjectPathsConfig, VyperLanguage, + ConfigurableArtifacts, Graph, Project, ProjectPathsConfig, RestrictionsWithVersion, + VyperLanguage, }; use inflector::Inflector; use regex::Regex; @@ -43,6 +45,7 @@ use semver::Version; use serde::{Deserialize, Serialize, Serializer}; use std::{ borrow::Cow, + collections::BTreeMap, fs, path::{Path, PathBuf}, str::FromStr, @@ -116,6 +119,9 @@ use vyper::VyperConfig; mod bind_json; use bind_json::BindJsonConfig; +mod compilation; +use compilation::{CompilationRestrictions, SettingsOverrides}; + /// Foundry configuration /// /// # Defaults @@ -479,6 +485,14 @@ pub struct Config { #[serde(rename = "__warnings", default, skip_serializing)] pub warnings: Vec, + /// Additional settings profiles to use when compiling. + #[serde(default)] + pub additional_compiler_profiles: Vec, + + /// Restrictions on compilation of certain files. + #[serde(default)] + pub compilation_restrictions: Vec, + /// PRIVATE: This structure may grow, As such, constructing this structure should /// _always_ be done using a public constructor or update syntax: /// @@ -867,12 +881,66 @@ impl Config { self.create_project(false, true) } + /// Builds mapping with additional settings profiles. + fn additional_settings( + &self, + base: &MultiCompilerSettings, + ) -> BTreeMap { + let mut map = BTreeMap::new(); + + for profile in &self.additional_compiler_profiles { + let mut settings = base.clone(); + profile.apply(&mut settings); + map.insert(profile.name.clone(), settings); + } + + map + } + + /// Resolves globs and builds a mapping from individual source files to their restrictions + fn restrictions( + &self, + paths: &ProjectPathsConfig, + ) -> Result>, SolcError> + { + let mut map = BTreeMap::new(); + + let graph = Graph::::resolve(paths)?; + let (sources, _) = graph.into_sources(); + + for res in &self.compilation_restrictions { + for source in sources.keys().filter(|path| { + if res.paths.is_match(path) { + true + } else if let Ok(path) = path.strip_prefix(&paths.root) { + res.paths.is_match(path) + } else { + false + } + }) { + let res: RestrictionsWithVersion<_> = + res.clone().try_into().map_err(SolcError::msg)?; + if !map.contains_key(source) { + map.insert(source.clone(), res); + } else { + map.get_mut(source.as_path()).unwrap().merge(res); + } + } + } + + Ok(map) + } + /// Creates a [Project] with the given `cached` and `no_artifacts` flags pub fn create_project(&self, cached: bool, no_artifacts: bool) -> Result { + let settings = self.compiler_settings()?; + let paths = self.project_paths(); let mut builder = Project::builder() .artifacts(self.configured_artifacts_handler()) - .paths(self.project_paths()) - .settings(self.compiler_settings()?) + .additional_settings(self.additional_settings(&settings)) + .restrictions(self.restrictions(&paths)?) + .settings(settings) + .paths(paths) .ignore_error_codes(self.ignored_error_codes.iter().copied().map(Into::into)) .ignore_paths(self.ignored_file_paths.clone()) .set_compiler_severity_filter(if self.deny_warnings { @@ -2243,6 +2311,8 @@ impl Default for Config { eof_version: None, alphanet: false, transaction_timeout: 120, + additional_compiler_profiles: Default::default(), + compilation_restrictions: Default::default(), eof: false, _non_exhaustive: (), } diff --git a/crates/forge/bin/cmd/bind_json.rs b/crates/forge/bin/cmd/bind_json.rs index c6a052836..de7a5a7a7 100644 --- a/crates/forge/bin/cmd/bind_json.rs +++ b/crates/forge/bin/cmd/bind_json.rs @@ -11,7 +11,7 @@ use foundry_compilers::{ multi::{MultiCompilerLanguage, MultiCompilerParsedSource}, project::ProjectCompiler, solc::SolcLanguage, - CompilerSettings, Graph, Project, + Graph, Project, }; use foundry_config::Config; use itertools::Itertools; @@ -72,7 +72,7 @@ impl BindJsonArgs { // We only generate bindings for a single Solidity version to avoid conflicts. let mut sources = graph // resolve graph into mapping language -> version -> sources - .into_sources_by_version(project.offline, &project.locked_versions, &project.compiler)? + .into_sources_by_version(&project)? .0 .into_iter() // we are only interested in Solidity sources @@ -81,7 +81,7 @@ impl BindJsonArgs { .1 .into_iter() // For now, we are always picking the latest version. - .max_by(|(v1, _), (v2, _)| v1.cmp(v2)) + .max_by(|(v1, _, _), (v2, _, _)| v1.cmp(v2)) .unwrap() .1; @@ -229,7 +229,7 @@ impl PreprocessedState { fn compile(self) -> Result { let Self { sources, target_path, mut project, config } = self; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::ast_output_selection(); }); diff --git a/crates/forge/bin/cmd/compiler.rs b/crates/forge/bin/cmd/compiler.rs index a7115c487..f5d62b671 100644 --- a/crates/forge/bin/cmd/compiler.rs +++ b/crates/forge/bin/cmd/compiler.rs @@ -63,18 +63,14 @@ impl ResolveArgs { let project = config.project()?; let graph = Graph::resolve(&project.paths)?; - let (sources, _) = graph.into_sources_by_version( - project.offline, - &project.locked_versions, - &project.compiler, - )?; + let (sources, _) = graph.into_sources_by_version(&project)?; let mut output: BTreeMap> = BTreeMap::new(); for (language, sources) in sources { let mut versions_with_paths: Vec = sources .iter() - .map(|(version, sources)| { + .map(|(version, sources, _)| { let paths: Vec = sources .iter() .filter_map(|(path_file, _)| { diff --git a/crates/forge/bin/cmd/create.rs b/crates/forge/bin/cmd/create.rs index 83494acb9..e19feafcc 100644 --- a/crates/forge/bin/cmd/create.rs +++ b/crates/forge/bin/cmd/create.rs @@ -20,7 +20,9 @@ use foundry_common::{ fmt::parse_tokens, shell, }; -use foundry_compilers::{artifacts::BytecodeObject, info::ContractInfo, utils::canonicalize}; +use foundry_compilers::{ + artifacts::BytecodeObject, info::ContractInfo, utils::canonicalize, ArtifactId, +}; use foundry_config::{ figment::{ self, @@ -106,9 +108,9 @@ impl CreateArgs { project.find_contract_path(&self.contract.name)? }; - let mut output = compile::compile_target(&target_path, &project, shell::is_json())?; + let output = compile::compile_target(&target_path, &project, shell::is_json())?; - let (abi, bin, _) = remove_contract(&mut output, &target_path, &self.contract.name)?; + let (abi, bin, id) = remove_contract(output, &target_path, &self.contract.name)?; let bin = match bin.object { BytecodeObject::Bytecode(_) => bin.object, @@ -148,8 +150,17 @@ impl CreateArgs { if self.unlocked { // Deploy with unlocked account let sender = self.eth.wallet.from.expect("required"); - self.deploy(abi, bin, params, provider, chain_id, sender, config.transaction_timeout) - .await + self.deploy( + abi, + bin, + params, + provider, + chain_id, + sender, + config.transaction_timeout, + id, + ) + .await } else { // Deploy with signer let signer = self.eth.wallet.signer().await?; @@ -157,8 +168,17 @@ impl CreateArgs { let provider = ProviderBuilder::<_, _, AnyNetwork>::default() .wallet(EthereumWallet::new(signer)) .on_provider(provider); - self.deploy(abi, bin, params, provider, chain_id, deployer, config.transaction_timeout) - .await + self.deploy( + abi, + bin, + params, + provider, + chain_id, + deployer, + config.transaction_timeout, + id, + ) + .await } } @@ -177,13 +197,14 @@ impl CreateArgs { &self, constructor_args: Option, chain: u64, + id: &ArtifactId, ) -> Result<()> { // NOTE: this does not represent the same `VerifyArgs` that would be sent after deployment, // since we don't know the address yet. let mut verify = forge_verify::VerifyArgs { address: Default::default(), contract: Some(self.contract.clone()), - compiler_version: None, + compiler_version: Some(id.version.to_string()), constructor_args, constructor_args_path: None, num_of_optimizations: None, @@ -204,6 +225,7 @@ impl CreateArgs { evm_version: self.opts.compiler.evm_version, show_standard_json_input: self.show_standard_json_input, guess_constructor_args: false, + compilation_profile: Some(id.profile.to_string()), }; // Check config for Etherscan API Keys to avoid preflight check failing if no @@ -229,6 +251,7 @@ impl CreateArgs { chain: u64, deployer_address: Address, timeout: u64, + id: ArtifactId, ) -> Result<()> { let bin = bin.into_bytes().unwrap_or_else(|| { panic!("no bytecode found in bin object for {}", self.contract.name) @@ -305,7 +328,7 @@ impl CreateArgs { constructor_args = Some(hex::encode(encoded_args)); } - self.verify_preflight_check(constructor_args.clone(), chain).await?; + self.verify_preflight_check(constructor_args.clone(), chain, &id).await?; } // Deploy the actual contract @@ -339,7 +362,7 @@ impl CreateArgs { let verify = forge_verify::VerifyArgs { address, contract: Some(self.contract), - compiler_version: None, + compiler_version: Some(id.version.to_string()), constructor_args, constructor_args_path: None, num_of_optimizations, @@ -357,6 +380,7 @@ impl CreateArgs { evm_version: self.opts.compiler.evm_version, show_standard_json_input: self.show_standard_json_input, guess_constructor_args: false, + compilation_profile: Some(id.profile.to_string()), }; sh_println!("Waiting for {} to detect contract deployment...", verify.verifier.verifier)?; verify.run().await diff --git a/crates/forge/bin/cmd/eip712.rs b/crates/forge/bin/cmd/eip712.rs index 5014d38d7..eb1d8dc1d 100644 --- a/crates/forge/bin/cmd/eip712.rs +++ b/crates/forge/bin/cmd/eip712.rs @@ -2,14 +2,10 @@ use clap::{Parser, ValueHint}; use eyre::{Ok, OptionExt, Result}; use foundry_cli::{opts::CoreBuildArgs, utils::LoadConfig}; use foundry_common::compile::ProjectCompiler; -use foundry_compilers::{ - artifacts::{ - output_selection::OutputSelection, - visitor::{Visitor, Walk}, - ContractDefinition, EnumDefinition, SourceUnit, StructDefinition, TypeDescriptions, - TypeName, - }, - CompilerSettings, +use foundry_compilers::artifacts::{ + output_selection::OutputSelection, + visitor::{Visitor, Walk}, + ContractDefinition, EnumDefinition, SourceUnit, StructDefinition, TypeDescriptions, TypeName, }; use std::{collections::BTreeMap, fmt::Write, path::PathBuf}; @@ -31,7 +27,7 @@ impl Eip712Args { let config = self.try_load_config_emit_warnings()?; let mut project = config.create_project(false, true)?; let target_path = dunce::canonicalize(self.target_path)?; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::ast_output_selection(); }); diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 613d57078..4e811bcbf 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -23,7 +23,7 @@ use foundry_cli::{ use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell, TestFunctionExt}; use foundry_compilers::{ artifacts::output_selection::OutputSelection, - compilers::{multi::MultiCompilerLanguage, CompilerSettings, Language}, + compilers::{multi::MultiCompilerLanguage, Language}, utils::source_files_iter, ProjectCompileOutput, }; @@ -203,7 +203,7 @@ impl TestArgs { filter: &ProjectPathsAwareFilter, ) -> Result> { let mut project = config.create_project(true, true)?; - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::common_output_selection(["abi".to_string()]); }); diff --git a/crates/forge/tests/cli/config.rs b/crates/forge/tests/cli/config.rs index 11bcd49e2..db87a85ba 100644 --- a/crates/forge/tests/cli/config.rs +++ b/crates/forge/tests/cli/config.rs @@ -154,6 +154,8 @@ forgetest!(can_extract_config_values, |prj, cmd| { eof_version: None, alphanet: false, transaction_timeout: 120, + additional_compiler_profiles: Default::default(), + compilation_restrictions: Default::default(), eof: false, _non_exhaustive: (), }; diff --git a/crates/script/src/verify.rs b/crates/script/src/verify.rs index 55435c559..220991703 100644 --- a/crates/script/src/verify.rs +++ b/crates/script/src/verify.rs @@ -155,6 +155,7 @@ impl VerifyBundle { evm_version: None, show_standard_json_input: false, guess_constructor_args: false, + compilation_profile: Some(artifact.profile.to_string()), }; return Some(verify) diff --git a/crates/verify/src/etherscan/flatten.rs b/crates/verify/src/etherscan/flatten.rs index ffe1496ca..a0b3defd7 100644 --- a/crates/verify/src/etherscan/flatten.rs +++ b/crates/verify/src/etherscan/flatten.rs @@ -90,7 +90,7 @@ impl EtherscanFlattenedSource { let out = SolcCompiler::Specific(solc).compile(&input)?; if out.errors.iter().any(|e| e.is_error()) { let mut o = AggregatedCompilerOutput::::default(); - o.extend(version, RawBuildInfo::new(&input, &out, false)?, out); + o.extend(version, RawBuildInfo::new(&input, &out, false)?, "default", out); let diags = o.diagnostics(&[], &[], Default::default()); eyre::bail!( diff --git a/crates/verify/src/etherscan/standard_json.rs b/crates/verify/src/etherscan/standard_json.rs index cab3010fa..e2fb5d2a4 100644 --- a/crates/verify/src/etherscan/standard_json.rs +++ b/crates/verify/src/etherscan/standard_json.rs @@ -18,7 +18,8 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource { .wrap_err("Failed to get standard json input")? .normalize_evm_version(&context.compiler_version); - input.settings.libraries.libs = input + let mut settings = context.compiler_settings.solc.settings.clone(); + settings.libraries.libs = input .settings .libraries .libs @@ -28,8 +29,12 @@ impl EtherscanSourceProvider for EtherscanStandardJsonSource { }) .collect(); + settings.remappings = input.settings.remappings; + // remove all incompatible settings - input.settings.sanitize(&context.compiler_version, SolcLanguage::Solidity); + settings.sanitize(&context.compiler_version, SolcLanguage::Solidity); + + input.settings = settings; let source = serde_json::to_string(&input).wrap_err("Failed to parse standard json input")?; diff --git a/crates/verify/src/provider.rs b/crates/verify/src/provider.rs index bc01bd9e3..ab6c5e9f6 100644 --- a/crates/verify/src/provider.rs +++ b/crates/verify/src/provider.rs @@ -9,7 +9,8 @@ use eyre::{OptionExt, Result}; use foundry_common::compile::ProjectCompiler; use foundry_compilers::{ artifacts::{output_selection::OutputSelection, Metadata, Source}, - compilers::{multi::MultiCompilerParsedSource, solc::SolcCompiler, CompilerSettings}, + compilers::{multi::MultiCompilerParsedSource, solc::SolcCompiler}, + multi::MultiCompilerSettings, solc::Solc, Graph, Project, }; @@ -25,6 +26,7 @@ pub struct VerificationContext { pub target_path: PathBuf, pub target_name: String, pub compiler_version: Version, + pub compiler_settings: MultiCompilerSettings, } impl VerificationContext { @@ -33,6 +35,7 @@ impl VerificationContext { target_name: String, compiler_version: Version, config: Config, + compiler_settings: MultiCompilerSettings, ) -> Result { let mut project = config.project()?; project.no_artifacts = true; @@ -40,13 +43,13 @@ impl VerificationContext { let solc = Solc::find_or_install(&compiler_version)?; project.compiler.solc = Some(SolcCompiler::Specific(solc)); - Ok(Self { config, project, target_name, target_path, compiler_version }) + Ok(Self { config, project, target_name, target_path, compiler_version, compiler_settings }) } /// Compiles target contract requesting only ABI and returns it. pub fn get_target_abi(&self) -> Result { let mut project = self.project.clone(); - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::common_output_selection(["abi".to_string()]) }); @@ -65,7 +68,7 @@ impl VerificationContext { /// Compiles target file requesting only metadata and returns it. pub fn get_target_metadata(&self) -> Result { let mut project = self.project.clone(); - project.settings.update_output_selection(|selection| { + project.update_output_selection(|selection| { *selection = OutputSelection::common_output_selection(["metadata".to_string()]); }); diff --git a/crates/verify/src/verify.rs b/crates/verify/src/verify.rs index 89cfd99aa..9c32ee95f 100644 --- a/crates/verify/src/verify.rs +++ b/crates/verify/src/verify.rs @@ -80,6 +80,10 @@ pub struct VerifyArgs { #[arg(long, value_name = "VERSION")] pub compiler_version: Option, + /// The compilation profile to use to build the smart contract. + #[arg(long, value_name = "PROFILE_NAME")] + pub compilation_profile: Option, + /// The number of optimization runs used to build the smart contract. #[arg(long, visible_alias = "optimizer-runs", value_name = "NUM")] pub num_of_optimizations: Option, @@ -258,6 +262,8 @@ impl VerifyArgs { project.find_contract_path(&contract.name)? }; + let cache = project.read_cache_file().ok(); + let version = if let Some(ref version) = self.compiler_version { version.trim_start_matches('v').parse()? } else if let Some(ref solc) = config.solc { @@ -265,10 +271,8 @@ impl VerifyArgs { SolcReq::Version(version) => version.to_owned(), SolcReq::Local(solc) => Solc::new(solc)?.version, } - } else if let Some(entry) = project - .read_cache_file() - .ok() - .and_then(|mut cache| cache.files.remove(&contract_path)) + } else if let Some(entry) = + cache.as_ref().and_then(|cache| cache.files.get(&contract_path).cloned()) { let unique_versions = entry .artifacts @@ -291,7 +295,48 @@ impl VerifyArgs { eyre::bail!("If cache is disabled, compiler version must be either provided with `--compiler-version` option or set in foundry.toml") }; - VerificationContext::new(contract_path, contract.name.clone(), version, config) + let settings = if let Some(profile) = &self.compilation_profile { + if profile == "default" { + &project.settings + } else if let Some(settings) = project.additional_settings.get(profile.as_str()) { + settings + } else { + eyre::bail!("Unknown compilation profile: {}", profile) + } + } else if let Some((cache, entry)) = cache + .as_ref() + .and_then(|cache| Some((cache, cache.files.get(&contract_path)?.clone()))) + { + let profiles = entry + .artifacts + .get(&contract.name) + .and_then(|artifacts| artifacts.get(&version)) + .map(|artifacts| artifacts.keys().collect::>()) + .unwrap_or_default(); + + if profiles.is_empty() { + eyre::bail!("No matching artifact found for {}", contract.name); + } else if profiles.len() > 1 { + eyre::bail!("Ambiguous compilation profiles found in cache: {}, please specify the profile through `--compilation-profile` flag", profiles.iter().join(", ")) + } + + let profile = profiles.into_iter().next().unwrap().to_owned(); + let settings = cache.profiles.get(&profile).expect("must be present"); + + settings + } else if project.additional_settings.is_empty() { + &project.settings + } else { + eyre::bail!("If cache is disabled, compilation profile must be provided with `--compiler-version` option or set in foundry.toml") + }; + + VerificationContext::new( + contract_path, + contract.name.clone(), + version, + config, + settings.clone(), + ) } else { if config.get_rpc_url().is_none() { eyre::bail!("You have to provide a contract name or a valid RPC URL") @@ -311,11 +356,19 @@ impl VerifyArgs { )) }; + let settings = project + .settings_profiles() + .find_map(|(name, settings)| { + (name == artifact_id.profile.as_str()).then_some(settings) + }) + .expect("must be present"); + VerificationContext::new( artifact_id.source.clone(), artifact_id.name.split('.').next().unwrap().to_owned(), artifact_id.version.clone(), config, + settings.clone(), ) } } From c13d42e850da353c0856a8b0d4123e13cc40045d Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 19 Nov 2024 01:27:51 +0400 Subject: [PATCH 39/58] fix: identification of contracts in scripts (#9346) * fix: identification of contracts in scripts * clippy --- crates/script/src/simulate.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index f8f9c9a36..a9798c43e 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -16,7 +16,7 @@ use eyre::{Context, Result}; use forge_script_sequence::{ScriptSequence, TransactionWithMetadata}; use foundry_cheatcodes::Wallets; use foundry_cli::utils::{has_different_gas_calc, now}; -use foundry_common::{get_contract_name, ContractData}; +use foundry_common::ContractData; use foundry_evm::traces::{decode_trace_arena, render_trace_arena}; use futures::future::{join_all, try_join_all}; use parking_lot::RwLock; @@ -205,9 +205,8 @@ impl PreSimulationState { .contracts .iter() .filter_map(move |(addr, contract_id)| { - let contract_name = get_contract_name(contract_id); if let Ok(Some((_, data))) = - self.build_data.known_contracts.find_by_name_or_identifier(contract_name) + self.build_data.known_contracts.find_by_name_or_identifier(contract_id) { return Some((*addr, data)); } From dacf3410e84bab1d8bab34a3c53364ab4fca4063 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:44:53 +0200 Subject: [PATCH 40/58] fix(`coverage`): allow `ir-minimum` for versions < 0.8.5 (#9341) * fix(coverage): allow ir-minimum for versions < 0.8.5 * Fix * Remove 0.8.13 restriction, update message and sanitize for 0.8.4 if version cannot be detected * Update crates/forge/bin/cmd/coverage.rs Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: DaniPopes <57450786+DaniPopes@users.noreply.github.com> --- crates/forge/bin/cmd/coverage.rs | 27 +++++++++++------------- crates/forge/tests/cli/coverage.rs | 34 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/crates/forge/bin/cmd/coverage.rs b/crates/forge/bin/cmd/coverage.rs index 56b2024e3..7e60a5451 100644 --- a/crates/forge/bin/cmd/coverage.rs +++ b/crates/forge/bin/cmd/coverage.rs @@ -16,7 +16,7 @@ use forge::{ use foundry_cli::utils::{LoadConfig, STATIC_FUZZ_SEED}; use foundry_common::{compile::ProjectCompiler, fs}; use foundry_compilers::{ - artifacts::{sourcemap::SourceMap, CompactBytecode, CompactDeployedBytecode}, + artifacts::{sourcemap::SourceMap, CompactBytecode, CompactDeployedBytecode, SolcLanguage}, Artifact, ArtifactId, Project, ProjectCompileOutput, }; use foundry_config::{Config, SolcReq}; @@ -94,23 +94,12 @@ impl CoverageArgs { // Set up the project let mut project = config.create_project(false, false)?; if self.ir_minimum { - // TODO: How to detect solc version if the user does not specify a solc version in - // config case1: specify local installed solc ? - // case2: multiple solc versions used and auto_detect_solc == true - if let Some(SolcReq::Version(version)) = &config.solc { - if *version < Version::new(0, 8, 13) { - return Err(eyre::eyre!( - "viaIR with minimum optimization is only available in Solidity 0.8.13 and above." - )); - } - } - // print warning message sh_warn!("{}", concat!( - "Warning! \"--ir-minimum\" flag enables viaIR with minimum optimization, \ + "`--ir-minimum` enables viaIR with minimum optimization, \ which can result in inaccurate source mappings.\n", "Only use this flag as a workaround if you are experiencing \"stack too deep\" errors.\n", - "Note that \"viaIR\" is only available in Solidity 0.8.13 and above.\n", + "Note that \"viaIR\" is production ready since Solidity 0.8.13 and above.\n", "See more: https://github.com/foundry-rs/foundry/issues/3357", ))?; @@ -119,7 +108,15 @@ impl CoverageArgs { // And also in new releases of solidity: // https://github.com/ethereum/solidity/issues/13972#issuecomment-1628632202 project.settings.solc.settings = - project.settings.solc.settings.with_via_ir_minimum_optimization() + project.settings.solc.settings.with_via_ir_minimum_optimization(); + let version = if let Some(SolcReq::Version(version)) = &config.solc { + version + } else { + // Sanitize settings for solc 0.8.4 if version cannot be detected. + // See . + &Version::new(0, 8, 4) + }; + project.settings.solc.settings.sanitize(version, SolcLanguage::Solidity); } else { project.settings.solc.optimizer.disable(); project.settings.solc.optimizer.runs = None; diff --git a/crates/forge/tests/cli/coverage.rs b/crates/forge/tests/cli/coverage.rs index 0ed272ae2..65900c592 100644 --- a/crates/forge/tests/cli/coverage.rs +++ b/crates/forge/tests/cli/coverage.rs @@ -1413,3 +1413,37 @@ contract AContractTest is DSTest { "#]]); }); + +// +// Test coverage with `--ir-minimum` for solidity < 0.8.5. +forgetest!(test_ir_minimum_coverage, |prj, cmd| { + prj.insert_ds_test(); + prj.add_source( + "AContract.sol", + r#" +pragma solidity 0.8.4; + +contract AContract { + function isContract(address account) internal view returns (bool) { + bytes32 codehash; + bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; + assembly { + codehash := extcodehash(account) + } + return (codehash != accountHash && codehash != 0x0); + } +} + "#, + ) + .unwrap(); + + // Assert coverage doesn't fail with `Error: Unknown key "inliner"`. + cmd.arg("coverage").arg("--ir-minimum").assert_success().stdout_eq(str![[r#" +... +| File | % Lines | % Statements | % Branches | % Funcs | +|-------------------|-------------|--------------|---------------|-------------| +| src/AContract.sol | 0.00% (0/4) | 0.00% (0/4) | 100.00% (0/0) | 0.00% (0/1) | +| Total | 0.00% (0/4) | 0.00% (0/4) | 100.00% (0/0) | 0.00% (0/1) | + +"#]]); +}); From 25b317afd1387da82deca96e2b98d9a9c7b34784 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:23:05 +0100 Subject: [PATCH 41/58] chore: don't color error message in red (#9352) * chore: don't color error message in red * Update crates/cli/src/handler.rs Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> --- crates/cli/src/handler.rs | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/crates/cli/src/handler.rs b/crates/cli/src/handler.rs index b2fbb49d4..ed32fa16b 100644 --- a/crates/cli/src/handler.rs +++ b/crates/cli/src/handler.rs @@ -1,21 +1,16 @@ use eyre::EyreHandler; -use std::error::Error; -use yansi::Paint; +use std::{error::Error, fmt}; /// A custom context type for Foundry specific error reporting via `eyre` #[derive(Debug)] pub struct Handler; impl EyreHandler for Handler { - fn debug( - &self, - error: &(dyn Error + 'static), - f: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { + fn debug(&self, error: &(dyn Error + 'static), f: &mut fmt::Formatter<'_>) -> fmt::Result { if f.alternate() { - return core::fmt::Debug::fmt(error, f) + return fmt::Debug::fmt(error, f) } - write!(f, "{}", error.red())?; + write!(f, "{error}")?; if let Some(cause) = error.source() { write!(f, "\n\nContext:")?; @@ -37,7 +32,7 @@ impl EyreHandler for Handler { } } -/// Installs the Foundry eyre hook as the global error report hook. +/// Installs the Foundry [eyre] and [panic](mod@std::panic) hooks as the global ones. /// /// # Details /// @@ -51,19 +46,17 @@ pub fn install() { std::env::set_var("RUST_BACKTRACE", "1"); } - if std::env::var_os("FOUNDRY_DEBUG").is_some() { - if let Err(e) = color_eyre::install() { - debug!("failed to install color eyre error hook: {e}"); - } + let panic_section = + "This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry"; + let (panic_hook, debug_eyre_hook) = + color_eyre::config::HookBuilder::default().panic_section(panic_section).into_hooks(); + panic_hook.install(); + let eyre_install_result = if std::env::var_os("FOUNDRY_DEBUG").is_some() { + debug_eyre_hook.install() } else { - let (panic_hook, _) = color_eyre::config::HookBuilder::default() - .panic_section( - "This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry", - ) - .into_hooks(); - panic_hook.install(); - if let Err(e) = eyre::set_hook(Box::new(move |_| Box::new(Handler))) { - debug!("failed to install eyre error hook: {e}"); - } + eyre::set_hook(Box::new(|_| Box::new(Handler))) + }; + if let Err(e) = eyre_install_result { + debug!("failed to install eyre error hook: {e}"); } } From 19249c3874146ec1a60c35fbe7800f9f21319207 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:23:21 +0100 Subject: [PATCH 42/58] chore: remove redundant 'setup failed' in setup errors (#9354) --- crates/forge/src/runner.rs | 10 ++-------- crates/forge/tests/it/core.rs | 10 ++-------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index 8ed3706de..1302c39ad 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -157,15 +157,9 @@ impl ContractRunner<'_> { raw: RawCallResult { traces, labels, logs, coverage, .. }, reason, } = *err; - (logs, traces, labels, Some(format!("setup failed: {reason}")), coverage) + (logs, traces, labels, Some(reason), coverage) } - Err(err) => ( - Vec::new(), - None, - HashMap::default(), - Some(format!("setup failed: {err}")), - None, - ), + Err(err) => (Vec::new(), None, HashMap::default(), Some(err.to_string()), None), }; traces.extend(setup_traces.map(|traces| (TraceKind::Setup, traces))); logs.extend(setup_logs); diff --git a/crates/forge/tests/it/core.rs b/crates/forge/tests/it/core.rs index abab87d28..c8a599195 100644 --- a/crates/forge/tests/it/core.rs +++ b/crates/forge/tests/it/core.rs @@ -23,7 +23,7 @@ async fn test_core() { vec![( "setUp()", false, - Some("setup failed: revert: setup failed predictably".to_string()), + Some("revert: setup failed predictably".to_string()), None, None, )], @@ -70,13 +70,7 @@ async fn test_core() { ), ( "default/core/FailingTestAfterFailedSetup.t.sol:FailingTestAfterFailedSetupTest", - vec![( - "setUp()", - false, - Some("setup failed: execution error".to_string()), - None, - None, - )], + vec![("setUp()", false, Some("execution error".to_string()), None, None)], ), ( "default/core/MultipleAfterInvariant.t.sol:MultipleAfterInvariant", From 9b490823166927b218e62d86ac183c87aaf923ce Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 19 Nov 2024 15:50:13 +0100 Subject: [PATCH 43/58] chore: make environment variable error nicer (#9353) --- crates/config/src/resolve.rs | 18 +++++++++++++----- testdata/default/cheats/RpcUrls.t.sol | 4 +--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/crates/config/src/resolve.rs b/crates/config/src/resolve.rs index 179ecffa2..20606cb11 100644 --- a/crates/config/src/resolve.rs +++ b/crates/config/src/resolve.rs @@ -23,15 +23,23 @@ impl UnresolvedEnvVarError { pub fn try_resolve(&self) -> Result { interpolate(&self.unresolved) } + + fn is_simple(&self) -> bool { + RE_PLACEHOLDER.captures_iter(&self.unresolved).count() <= 1 + } } impl fmt::Display for UnresolvedEnvVarError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "Failed to resolve env var `{}` in `{}`: {}", - self.var, self.unresolved, self.source - ) + write!(f, "environment variable `{}` ", self.var)?; + f.write_str(match self.source { + VarError::NotPresent => "not found", + VarError::NotUnicode(_) => "is not valid unicode", + })?; + if !self.is_simple() { + write!(f, " in `{}`", self.unresolved)?; + } + Ok(()) } } diff --git a/testdata/default/cheats/RpcUrls.t.sol b/testdata/default/cheats/RpcUrls.t.sol index aaa5a00bd..9425d5963 100644 --- a/testdata/default/cheats/RpcUrls.t.sol +++ b/testdata/default/cheats/RpcUrls.t.sol @@ -22,9 +22,7 @@ contract RpcUrlTest is DSTest { // can set env and return correct url function testCanSetAndGetURLAndAllUrls() public { // this will fail because alias is not set - vm._expectCheatcodeRevert( - "Failed to resolve env var `RPC_ENV_ALIAS` in `${RPC_ENV_ALIAS}`: environment variable not found" - ); + vm._expectCheatcodeRevert("environment variable `RPC_ENV_ALIAS` not found"); string[2][] memory _urls = vm.rpcUrls(); string memory url = vm.rpcUrl("mainnet"); From 9f0c26d9b61e6b1c0536945391a7158d68eda32c Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:33:23 +0100 Subject: [PATCH 44/58] test: update external forge-std (#9356) --- crates/forge/tests/cli/ext_integration.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/forge/tests/cli/ext_integration.rs b/crates/forge/tests/cli/ext_integration.rs index b2747e3cc..e9437f04c 100644 --- a/crates/forge/tests/cli/ext_integration.rs +++ b/crates/forge/tests/cli/ext_integration.rs @@ -2,7 +2,7 @@ use foundry_test_utils::util::ExtTester; #[test] fn forge_std() { - ExtTester::new("foundry-rs", "forge-std", "1d0766bc5d814f117c7b1e643828f7d85024fb51") + ExtTester::new("foundry-rs", "forge-std", "2b59872eee0b8088ddcade39fe8c041e17bb79c0") // Skip fork tests. .args(["--nmc", "Fork"]) .run(); From 7538c4ed5a8575f403321d06c52882d3804eab3d Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Tue, 19 Nov 2024 18:48:29 +0200 Subject: [PATCH 45/58] chore(ci): archive endpoints config (#9348) * chore: move archive endpoints to different provider * Make archive endpoints configurable in env vars * Truncate fork url in err * Include only provider in failed fork message * Add env vars from secrets * Fix tests --------- Co-authored-by: Matthias Seitz --- .github/workflows/nextest.yml | 2 ++ Cargo.lock | 1 + crates/anvil/tests/it/fork.rs | 1 + crates/evm/core/Cargo.toml | 1 + crates/evm/core/src/opts.rs | 9 ++++++- crates/forge/tests/cli/test_cmd.rs | 28 +++++++++++++++++++++- crates/test-utils/src/rpc.rs | 38 ++++++++++++++++++++++++------ 7 files changed, 71 insertions(+), 9 deletions(-) diff --git a/.github/workflows/nextest.yml b/.github/workflows/nextest.yml index da862c657..6fc1a6703 100644 --- a/.github/workflows/nextest.yml +++ b/.github/workflows/nextest.yml @@ -91,4 +91,6 @@ jobs: - name: Test env: SVM_TARGET_PLATFORM: ${{ matrix.svm_target_platform }} + HTTP_ARCHIVE_URLS: ${{ secrets.HTTP_ARCHIVE_URLS }} + WS_ARCHIVE_URLS: ${{ secrets.WS_ARCHIVE_URLS }} run: cargo nextest run ${{ matrix.flags }} diff --git a/Cargo.lock b/Cargo.lock index 81adf0f4b..144c6e078 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3998,6 +3998,7 @@ dependencies = [ "thiserror 1.0.69", "tokio", "tracing", + "url", ] [[package]] diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index a35d7c267..821395417 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -1040,6 +1040,7 @@ async fn can_impersonate_in_fork() { // #[tokio::test(flavor = "multi_thread")] +#[ignore] async fn test_total_difficulty_fork() { let (api, handle) = spawn(fork_config()).await; diff --git a/crates/evm/core/Cargo.toml b/crates/evm/core/Cargo.toml index 464412016..c9f5131d7 100644 --- a/crates/evm/core/Cargo.toml +++ b/crates/evm/core/Cargo.toml @@ -59,6 +59,7 @@ serde_json.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["time", "macros"] } tracing.workspace = true +url.workspace = true [dev-dependencies] foundry-test-utils.workspace = true diff --git a/crates/evm/core/src/opts.rs b/crates/evm/core/src/opts.rs index 17ecbcca1..99cc8daba 100644 --- a/crates/evm/core/src/opts.rs +++ b/crates/evm/core/src/opts.rs @@ -8,6 +8,7 @@ use foundry_common::{provider::ProviderBuilder, ALCHEMY_FREE_TIER_CUPS}; use foundry_config::{Chain, Config}; use revm::primitives::{BlockEnv, CfgEnv, TxEnv}; use serde::{Deserialize, Deserializer, Serialize}; +use url::Url; #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct EvmOpts { @@ -102,7 +103,13 @@ impl EvmOpts { ) .await .wrap_err_with(|| { - format!("Could not instantiate forked environment with fork url: {fork_url}") + let mut err_msg = "Could not instantiate forked environment".to_string(); + if let Ok(url) = Url::parse(fork_url) { + if let Some(provider) = url.host() { + err_msg.push_str(&format!(" with provider {provider}")); + } + } + err_msg }) } diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index f51cf6703..8e064c63c 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -575,7 +575,7 @@ Compiler run successful! Ran 1 test for test/Contract.t.sol:USDTCallingTest [PASS] test() ([GAS]) Traces: - [9406] USDTCallingTest::test() + [..] USDTCallingTest::test() ├─ [0] VM::createSelectFork("[..]") │ └─ ← [Return] 0 ├─ [3110] 0xdAC17F958D2ee523a2206206994597C13D831ec7::name() [staticcall] @@ -2639,3 +2639,29 @@ contract ScrollForkTest is Test { cmd.args(["test", "--mt", "test_roll_scroll_fork_to_tx", "--evm-version", "cancun"]) .assert_success(); }); + +// Test that only provider is included in failed fork error. +forgetest_init!(test_display_provider_on_error, |prj, cmd| { + prj.add_test( + "ForkTest.t.sol", + r#" +import {Test} from "forge-std/Test.sol"; + +contract ForkTest is Test { + function test_fork_err_message() public { + vm.createSelectFork("https://eth-mainnet.g.alchemy.com/v2/DUMMY_KEY"); + } +} + "#, + ) + .unwrap(); + + cmd.args(["test", "--mt", "test_fork_err_message"]).assert_failure().stdout_eq(str![[r#" +... +Ran 1 test for test/ForkTest.t.sol:ForkTest +[FAIL: vm.createSelectFork: Could not instantiate forked environment with provider eth-mainnet.g.alchemy.com;] test_fork_err_message() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] +... + +"#]]); +}); diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index 44deda60c..ba27f381c 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -2,11 +2,19 @@ use foundry_config::{NamedChain, NamedChain::Optimism}; use rand::seq::SliceRandom; -use std::sync::{ - atomic::{AtomicUsize, Ordering}, - LazyLock, +use std::{ + env, + sync::{ + atomic::{AtomicUsize, Ordering}, + LazyLock, + }, }; +/// Env var key for ws archive endpoints. +const ENV_WS_ARCHIVE_ENDPOINTS: &str = "WS_ARCHIVE_URLS"; +/// Env var key for http archive endpoints. +const ENV_HTTP_ARCHIVE_ENDPOINTS: &str = "HTTP_ARCHIVE_URLS"; + // List of general purpose infura keys to rotate through static INFURA_KEYS: LazyLock> = LazyLock::new(|| { let mut keys = vec![ @@ -118,14 +126,30 @@ pub fn next_ws_endpoint(chain: NamedChain) -> String { /// Returns endpoint that has access to archive state pub fn next_http_archive_rpc_endpoint() -> String { - let idx = next() % ALCHEMY_KEYS.len(); - format!("https://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) + next_archive_endpoint(false) } /// Returns endpoint that has access to archive state pub fn next_ws_archive_rpc_endpoint() -> String { - let idx = next() % ALCHEMY_KEYS.len(); - format!("wss://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) + next_archive_endpoint(true) +} + +/// Returns endpoint that has access to archive state, http or ws. +/// Use env vars (comma separated urls) or default inline keys (Alchemy for ws, Infura for http). +fn next_archive_endpoint(is_ws: bool) -> String { + let env_urls = if is_ws { ENV_WS_ARCHIVE_ENDPOINTS } else { ENV_HTTP_ARCHIVE_ENDPOINTS }; + + let rpc_env_vars = env::var(env_urls).unwrap_or_default(); + if !rpc_env_vars.is_empty() { + let urls = rpc_env_vars.split(',').collect::>(); + urls.choose(&mut rand::thread_rng()).unwrap().to_string() + } else if is_ws { + let idx = next() % ALCHEMY_KEYS.len(); + format!("wss://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) + } else { + let idx = next() % INFURA_KEYS.len(); + format!("https://mainnet.infura.io/v3/{}", INFURA_KEYS[idx]) + } } /// Returns the next etherscan api key From 4648d5c77f2ca8ee646464836f08be48b5072df6 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:46:45 +0200 Subject: [PATCH 46/58] chore: pick provider urls by next index (#9359) --- crates/test-utils/src/rpc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index ba27f381c..0934ea179 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -142,7 +142,8 @@ fn next_archive_endpoint(is_ws: bool) -> String { let rpc_env_vars = env::var(env_urls).unwrap_or_default(); if !rpc_env_vars.is_empty() { let urls = rpc_env_vars.split(',').collect::>(); - urls.choose(&mut rand::thread_rng()).unwrap().to_string() + let idx = next() % urls.len(); + urls[idx].to_string() } else if is_ws { let idx = next() % ALCHEMY_KEYS.len(); format!("wss://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) From d20c142d0655490122e79fb66aa119df3638bad6 Mon Sep 17 00:00:00 2001 From: Dmitry <98899785+mdqst@users.noreply.github.com> Date: Wed, 20 Nov 2024 10:57:17 +0300 Subject: [PATCH 47/58] fix: correct shell substitution in installer (#9351) Fix typographical error in default value assignment for FOUNDRY_DIR --- foundryup/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundryup/install b/foundryup/install index da8156a09..1a8bc8c6e 100755 --- a/foundryup/install +++ b/foundryup/install @@ -4,7 +4,7 @@ set -eo pipefail echo "Installing foundryup..." BASE_DIR="${XDG_CONFIG_HOME:-$HOME}" -FOUNDRY_DIR="${FOUNDRY_DIR-"$BASE_DIR/.foundry"}" +FOUNDRY_DIR="${FOUNDRY_DIR:-"$BASE_DIR/.foundry"}" FOUNDRY_BIN_DIR="$FOUNDRY_DIR/bin" FOUNDRY_MAN_DIR="$FOUNDRY_DIR/share/man/man1" From e5776932e865c28acf002371e6fce8d95017b0a1 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:39:20 +0100 Subject: [PATCH 48/58] chore: TestSetup cleanup (#9355) Co-authored-by: Matthias Seitz --- crates/evm/coverage/src/lib.rs | 8 ++ crates/evm/evm/src/executors/fuzz/mod.rs | 6 +- crates/evm/evm/src/executors/invariant/mod.rs | 5 +- .../evm/evm/src/executors/invariant/replay.rs | 10 +- crates/evm/evm/src/executors/mod.rs | 23 ++++ crates/forge/src/result.rs | 110 ++++++------------ crates/forge/src/runner.rs | 98 ++++++---------- 7 files changed, 103 insertions(+), 157 deletions(-) diff --git a/crates/evm/coverage/src/lib.rs b/crates/evm/coverage/src/lib.rs index 7ac609123..ad4ab53e3 100644 --- a/crates/evm/coverage/src/lib.rs +++ b/crates/evm/coverage/src/lib.rs @@ -174,6 +174,14 @@ impl CoverageReport { pub struct HitMaps(pub HashMap); impl HitMaps { + pub fn merge_opt(a: &mut Option, b: Option) { + match (a, b) { + (_, None) => {} + (a @ None, Some(b)) => *a = Some(b), + (Some(a), Some(b)) => a.merge(b), + } + } + pub fn merge(&mut self, other: Self) { for (code_hash, hit_map) in other.0 { if let Some(HitMap { hits: extra_hits, .. }) = self.insert(code_hash, hit_map) { diff --git a/crates/evm/evm/src/executors/fuzz/mod.rs b/crates/evm/evm/src/executors/fuzz/mod.rs index 982e44ea9..2bbe80a63 100644 --- a/crates/evm/evm/src/executors/fuzz/mod.rs +++ b/crates/evm/evm/src/executors/fuzz/mod.rs @@ -127,11 +127,7 @@ impl FuzzedExecutor { data.logs.extend(case.logs); } - // Collect and merge coverage if `forge snapshot` context. - match &mut data.coverage { - Some(prev) => prev.merge(case.coverage.unwrap()), - opt => *opt = case.coverage, - } + HitMaps::merge_opt(&mut data.coverage, case.coverage); data.deprecated_cheatcodes = case.deprecated_cheatcodes; diff --git a/crates/evm/evm/src/executors/invariant/mod.rs b/crates/evm/evm/src/executors/invariant/mod.rs index 860acdbb2..f98dd2111 100644 --- a/crates/evm/evm/src/executors/invariant/mod.rs +++ b/crates/evm/evm/src/executors/invariant/mod.rs @@ -204,10 +204,7 @@ impl InvariantTest { /// Merge current collected coverage with the new coverage from last fuzzed call. pub fn merge_coverage(&self, new_coverage: Option) { - match &mut self.execution_data.borrow_mut().coverage { - Some(prev) => prev.merge(new_coverage.unwrap()), - opt => *opt = new_coverage, - } + HitMaps::merge_opt(&mut self.execution_data.borrow_mut().coverage, new_coverage); } /// Update metrics for a fuzzed selector, extracted from tx details. diff --git a/crates/evm/evm/src/executors/invariant/replay.rs b/crates/evm/evm/src/executors/invariant/replay.rs index 969f1587f..36192a6d6 100644 --- a/crates/evm/evm/src/executors/invariant/replay.rs +++ b/crates/evm/evm/src/executors/invariant/replay.rs @@ -48,16 +48,10 @@ pub fn replay_run( tx.call_details.calldata.clone(), U256::ZERO, )?; + logs.extend(call_result.logs); traces.push((TraceKind::Execution, call_result.traces.clone().unwrap())); - - if let Some(new_coverage) = call_result.coverage { - if let Some(old_coverage) = coverage { - *coverage = Some(std::mem::take(old_coverage).merged(new_coverage)); - } else { - *coverage = Some(new_coverage); - } - } + HitMaps::merge_opt(coverage, call_result.coverage); // Identify newly generated contracts, if they exist. ided_contracts diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 723b520aa..6f458258a 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -713,6 +713,12 @@ impl std::ops::DerefMut for DeployResult { } } +impl From for RawCallResult { + fn from(d: DeployResult) -> Self { + d.raw + } +} + /// The result of a raw call. #[derive(Debug)] pub struct RawCallResult { @@ -780,6 +786,23 @@ impl Default for RawCallResult { } impl RawCallResult { + /// Unpacks an EVM result. + pub fn from_evm_result(r: Result) -> eyre::Result<(Self, Option)> { + match r { + Ok(r) => Ok((r, None)), + Err(EvmError::Execution(e)) => Ok((e.raw, Some(e.reason))), + Err(e) => Err(e.into()), + } + } + + /// Unpacks an execution result. + pub fn from_execution_result(r: Result) -> (Self, Option) { + match r { + Ok(r) => (r, None), + Err(e) => (e.raw, Some(e.reason)), + } + } + /// Converts the result of the call into an `EvmError`. pub fn into_evm_error(self, rd: Option<&RevertDecoder>) -> EvmError { if let Some(reason) = SkipReason::decode(&self.result) { diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index 60c07472e..7f02db577 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -13,7 +13,7 @@ use foundry_common::{evm::Breakpoints, get_contract_name, get_file_name, shell}; use foundry_evm::{ coverage::HitMaps, decode::SkipReason, - executors::{invariant::InvariantMetrics, EvmError, RawCallResult}, + executors::{invariant::InvariantMetrics, RawCallResult}, fuzz::{CounterExample, FuzzCase, FuzzFixtures, FuzzTestResult}, traces::{CallTraceArena, CallTraceDecoder, TraceKind, Traces}, }; @@ -469,7 +469,7 @@ impl TestResult { /// Creates a new test result starting from test setup results. pub fn new(setup: TestSetup) -> Self { Self { - labeled_addresses: setup.labeled_addresses, + labeled_addresses: setup.labels, logs: setup.logs, traces: setup.traces, coverage: setup.coverage, @@ -490,7 +490,7 @@ impl TestResult { logs: setup.logs, traces: setup.traces, coverage: setup.coverage, - labeled_addresses: setup.labeled_addresses, + labeled_addresses: setup.labels, ..Default::default() } } @@ -651,21 +651,17 @@ impl TestResult { format!("{self} {name} {}", self.kind.report()) } - /// Function to merge logs, addresses, traces and coverage from a call result into test result. - pub fn merge_call_result(&mut self, call_result: &RawCallResult) { - self.logs.extend(call_result.logs.clone()); - self.labeled_addresses.extend(call_result.labels.clone()); - self.traces.extend(call_result.traces.clone().map(|traces| (TraceKind::Execution, traces))); - self.merge_coverages(call_result.coverage.clone()); + /// Merges the given raw call result into `self`. + pub fn extend(&mut self, call_result: RawCallResult) { + self.logs.extend(call_result.logs); + self.labeled_addresses.extend(call_result.labels); + self.traces.extend(call_result.traces.map(|traces| (TraceKind::Execution, traces))); + self.merge_coverages(call_result.coverage); } - /// Function to merge given coverage in current test result coverage. + /// Merges the given coverage result into `self`. pub fn merge_coverages(&mut self, other_coverage: Option) { - let old_coverage = std::mem::take(&mut self.coverage); - self.coverage = match (old_coverage, other_coverage) { - (Some(old_coverage), Some(other)) => Some(old_coverage.merged(other)), - (a, b) => a.or(b), - }; + HitMaps::merge_opt(&mut self.coverage, other_coverage); } } @@ -747,77 +743,39 @@ impl TestKind { } } +/// The result of a test setup. +/// +/// Includes the deployment of the required libraries and the test contract itself, and the call to +/// the `setUp()` function. #[derive(Clone, Debug, Default)] pub struct TestSetup { - /// The address at which the test contract was deployed + /// The address at which the test contract was deployed. pub address: Address, - /// The logs emitted during setup + /// Defined fuzz test fixtures. + pub fuzz_fixtures: FuzzFixtures, + + /// The logs emitted during setup. pub logs: Vec, - /// Call traces of the setup + /// Addresses labeled during setup. + pub labels: AddressHashMap, + /// Call traces of the setup. pub traces: Traces, - /// Addresses labeled during setup - pub labeled_addresses: AddressHashMap, - /// The reason the setup failed, if it did - pub reason: Option, - /// Coverage info during setup + /// Coverage info during setup. pub coverage: Option, - /// Defined fuzz test fixtures - pub fuzz_fixtures: FuzzFixtures, + + /// The reason the setup failed, if it did. + pub reason: Option, } impl TestSetup { - pub fn from_evm_error_with( - error: EvmError, - mut logs: Vec, - mut traces: Traces, - mut labeled_addresses: AddressHashMap, - ) -> Self { - match error { - EvmError::Execution(err) => { - // force the tracekind to be setup so a trace is shown. - traces.extend(err.raw.traces.map(|traces| (TraceKind::Setup, traces))); - logs.extend(err.raw.logs); - labeled_addresses.extend(err.raw.labels); - Self::failed_with(logs, traces, labeled_addresses, err.reason) - } - e => Self::failed_with( - logs, - traces, - labeled_addresses, - format!("failed to deploy contract: {e}"), - ), - } - } - - pub fn success( - address: Address, - logs: Vec, - traces: Traces, - labeled_addresses: AddressHashMap, - coverage: Option, - fuzz_fixtures: FuzzFixtures, - ) -> Self { - Self { address, logs, traces, labeled_addresses, reason: None, coverage, fuzz_fixtures } - } - - pub fn failed_with( - logs: Vec, - traces: Traces, - labeled_addresses: AddressHashMap, - reason: String, - ) -> Self { - Self { - address: Address::ZERO, - logs, - traces, - labeled_addresses, - reason: Some(reason), - coverage: None, - fuzz_fixtures: FuzzFixtures::default(), - } - } - pub fn failed(reason: String) -> Self { Self { reason: Some(reason), ..Default::default() } } + + pub fn extend(&mut self, raw: RawCallResult, trace_kind: TraceKind) { + self.logs.extend(raw.logs); + self.labels.extend(raw.labels); + self.traces.extend(raw.traces.map(|traces| (trace_kind, traces))); + HitMaps::merge_opt(&mut self.coverage, raw.coverage); + } } diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index 1302c39ad..4b66a482c 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -24,7 +24,7 @@ use foundry_evm::{ invariant::{ check_sequence, replay_error, replay_run, InvariantExecutor, InvariantFuzzError, }, - CallResult, EvmError, ExecutionErr, Executor, ITest, RawCallResult, + CallResult, EvmError, Executor, ITest, RawCallResult, }, fuzz::{ fixture_name, @@ -88,53 +88,51 @@ impl ContractRunner<'_> { self.executor.set_balance(self.sender, U256::MAX)?; self.executor.set_balance(CALLER, U256::MAX)?; - // We set the nonce of the deployer accounts to 1 to get the same addresses as DappTools + // We set the nonce of the deployer accounts to 1 to get the same addresses as DappTools. self.executor.set_nonce(self.sender, 1)?; - // Deploy libraries + // Deploy libraries. self.executor.set_balance(LIBRARY_DEPLOYER, U256::MAX)?; - let mut logs = Vec::new(); - let mut traces = Vec::with_capacity(self.libs_to_deploy.len()); + let mut result = TestSetup::default(); for code in self.libs_to_deploy.iter() { - match self.executor.deploy( + let deploy_result = self.executor.deploy( LIBRARY_DEPLOYER, code.clone(), U256::ZERO, Some(self.revert_decoder), - ) { - Ok(d) => { - logs.extend(d.raw.logs); - traces.extend(d.raw.traces.map(|traces| (TraceKind::Deployment, traces))); - } - Err(e) => { - return Ok(TestSetup::from_evm_error_with(e, logs, traces, Default::default())) - } + ); + let (raw, reason) = RawCallResult::from_evm_result(deploy_result.map(Into::into))?; + result.extend(raw, TraceKind::Deployment); + if reason.is_some() { + result.reason = reason; + return Ok(result); } } let address = self.sender.create(self.executor.get_nonce(self.sender)?); + result.address = address; // Set the contracts initial balance before deployment, so it is available during // construction self.executor.set_balance(address, self.initial_balance)?; // Deploy the test contract - match self.executor.deploy( + let deploy_result = self.executor.deploy( self.sender, self.contract.bytecode.clone(), U256::ZERO, Some(self.revert_decoder), - ) { - Ok(d) => { - logs.extend(d.raw.logs); - traces.extend(d.raw.traces.map(|traces| (TraceKind::Deployment, traces))); - d.address - } - Err(e) => { - return Ok(TestSetup::from_evm_error_with(e, logs, traces, Default::default())) - } - }; + ); + if let Ok(dr) = &deploy_result { + debug_assert_eq!(dr.address, address); + } + let (raw, reason) = RawCallResult::from_evm_result(deploy_result.map(Into::into))?; + result.extend(raw, TraceKind::Deployment); + if reason.is_some() { + result.reason = reason; + return Ok(result); + } // Reset `self.sender`s, `CALLER`s and `LIBRARY_DEPLOYER`'s balance to the initial balance. self.executor.set_balance(self.sender, self.initial_balance)?; @@ -144,45 +142,15 @@ impl ContractRunner<'_> { self.executor.deploy_create2_deployer()?; // Optionally call the `setUp` function - let result = if call_setup { + if call_setup { trace!("calling setUp"); let res = self.executor.setup(None, address, Some(self.revert_decoder)); - let (setup_logs, setup_traces, labeled_addresses, reason, coverage) = match res { - Ok(RawCallResult { traces, labels, logs, coverage, .. }) => { - trace!(%address, "successfully called setUp"); - (logs, traces, labels, None, coverage) - } - Err(EvmError::Execution(err)) => { - let ExecutionErr { - raw: RawCallResult { traces, labels, logs, coverage, .. }, - reason, - } = *err; - (logs, traces, labels, Some(reason), coverage) - } - Err(err) => (Vec::new(), None, HashMap::default(), Some(err.to_string()), None), - }; - traces.extend(setup_traces.map(|traces| (TraceKind::Setup, traces))); - logs.extend(setup_logs); - - TestSetup { - address, - logs, - traces, - labeled_addresses, - reason, - coverage, - fuzz_fixtures: self.fuzz_fixtures(address), - } - } else { - TestSetup::success( - address, - logs, - traces, - Default::default(), - None, - self.fuzz_fixtures(address), - ) - }; + let (raw, reason) = RawCallResult::from_evm_result(res)?; + result.extend(raw, TraceKind::Setup); + result.reason = reason; + } + + result.fuzz_fixtures = self.fuzz_fixtures(address); Ok(result) } @@ -698,11 +666,13 @@ impl ContractRunner<'_> { // Apply before test configured calldata. match executor.to_mut().transact_raw(self.sender, address, calldata, U256::ZERO) { Ok(call_result) => { + let reverted = call_result.reverted; + // Merge tx result traces in unit test result. - test_result.merge_call_result(&call_result); + test_result.extend(call_result); // To continue unit test execution the call should not revert. - if call_result.reverted { + if reverted { return Err(test_result.single_fail(None)) } } From 3a954409e350164d6267ed72b8c3fb5a2f0a01c4 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:07:24 +0200 Subject: [PATCH 49/58] chore(ci): proper read of archive nodes (#9362) inherit secrets, use alchemy as default for external PRs, comment out infura --- .github/workflows/test.yml | 1 + crates/test-utils/src/rpc.rs | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index acb63a994..d5a2eabb0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,6 +18,7 @@ jobs: uses: ./.github/workflows/nextest.yml with: profile: default + secrets: inherit docs: runs-on: ubuntu-latest diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index 0934ea179..7bf820a20 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -18,9 +18,9 @@ const ENV_HTTP_ARCHIVE_ENDPOINTS: &str = "HTTP_ARCHIVE_URLS"; // List of general purpose infura keys to rotate through static INFURA_KEYS: LazyLock> = LazyLock::new(|| { let mut keys = vec![ - "6cb19d07ca2d44f59befd61563b1037b", - "6d46c0cca653407b861f3f93f7b0236a", - "69a36846dec146e3a2898429be60be85", + // "6cb19d07ca2d44f59befd61563b1037b", + // "6d46c0cca653407b861f3f93f7b0236a", + // "69a36846dec146e3a2898429be60be85", // "16a8be88795540b9b3903d8de0f7baa5", // "f4a0bdad42674adab5fc0ac077ffab2b", // "5c812e02193c4ba793f8c214317582bd", @@ -39,11 +39,11 @@ static ALCHEMY_KEYS: LazyLock> = LazyLock::new(|| { "GL4M0hfzSYGU5e1_t804HoUDOObWP-FA", "WV407BEiBmjNJfKo9Uo_55u0z0ITyCOX", "Ge56dH9siMF4T0whP99sQXOcr2mFs8wZ", - "QC55XC151AgkS3FNtWvz9VZGeu9Xd9lb", - "pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP", - "A5sZ85MIr4SzCMkT0zXh2eeamGIq3vGL", - "9VWGraLx0tMiSWx05WH-ywgSVmMxs66W", - "U4hsGWgl9lBM1j3jhSgJ4gbjHg2jRwKy", + // "QC55XC151AgkS3FNtWvz9VZGeu9Xd9lb", + // "pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP", + // "A5sZ85MIr4SzCMkT0zXh2eeamGIq3vGL", + // "9VWGraLx0tMiSWx05WH-ywgSVmMxs66W", + // "U4hsGWgl9lBM1j3jhSgJ4gbjHg2jRwKy", "K-uNlqYoYCO9cdBHcifwCDAcEjDy1UHL", "GWdgwabOE2XfBdLp_gIq-q6QHa7DSoag", "Uz0cF5HCXFtpZlvd9NR7kHxfB_Wdpsx7", @@ -148,8 +148,8 @@ fn next_archive_endpoint(is_ws: bool) -> String { let idx = next() % ALCHEMY_KEYS.len(); format!("wss://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) } else { - let idx = next() % INFURA_KEYS.len(); - format!("https://mainnet.infura.io/v3/{}", INFURA_KEYS[idx]) + let idx = next() % ALCHEMY_KEYS.len(); + format!("https://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) } } From 999cc1bf270bc9fd63af05b6dccbbf0743bf5e55 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 20 Nov 2024 12:30:59 +0100 Subject: [PATCH 50/58] chore(test-utils): simplify next calls (#9361) Co-authored-by: grandizzy --- crates/test-utils/src/rpc.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/crates/test-utils/src/rpc.rs b/crates/test-utils/src/rpc.rs index 7bf820a20..361bf56c2 100644 --- a/crates/test-utils/src/rpc.rs +++ b/crates/test-utils/src/rpc.rs @@ -91,13 +91,14 @@ static ETHERSCAN_OPTIMISM_KEYS: LazyLock> = LazyLock::new(|| vec!["JQNGFHINKS1W7Y5FRXU4SPBYF43J3NYK46"]); /// Returns the next index to use. -fn next() -> usize { +fn next_idx() -> usize { static NEXT_INDEX: AtomicUsize = AtomicUsize::new(0); NEXT_INDEX.fetch_add(1, Ordering::SeqCst) } -fn num_keys() -> usize { - INFURA_KEYS.len() + ALCHEMY_KEYS.len() +/// Returns the next item in the list to use. +fn next(list: &[T]) -> &T { + &list[next_idx() % list.len()] } /// Returns the next _mainnet_ rpc endpoint in inline @@ -142,21 +143,17 @@ fn next_archive_endpoint(is_ws: bool) -> String { let rpc_env_vars = env::var(env_urls).unwrap_or_default(); if !rpc_env_vars.is_empty() { let urls = rpc_env_vars.split(',').collect::>(); - let idx = next() % urls.len(); - urls[idx].to_string() + next(&urls).to_string() } else if is_ws { - let idx = next() % ALCHEMY_KEYS.len(); - format!("wss://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) + format!("wss://eth-mainnet.g.alchemy.com/v2/{}", next(&ALCHEMY_KEYS)) } else { - let idx = next() % ALCHEMY_KEYS.len(); - format!("https://eth-mainnet.g.alchemy.com/v2/{}", ALCHEMY_KEYS[idx]) + format!("https://eth-mainnet.g.alchemy.com/v2/{}", next(&ALCHEMY_KEYS)) } } /// Returns the next etherscan api key pub fn next_mainnet_etherscan_api_key() -> String { - let idx = next() % ETHERSCAN_MAINNET_KEYS.len(); - ETHERSCAN_MAINNET_KEYS[idx].to_string() + next_etherscan_api_key(NamedChain::Mainnet) } /// Returns the next etherscan api key for given chain. @@ -165,8 +162,7 @@ pub fn next_etherscan_api_key(chain: NamedChain) -> String { Optimism => ÐERSCAN_OPTIMISM_KEYS, _ => ÐERSCAN_MAINNET_KEYS, }; - let idx = next() % keys.len(); - keys[idx].to_string() + next(keys).to_string() } fn next_url(is_ws: bool, chain: NamedChain) -> String { @@ -176,7 +172,7 @@ fn next_url(is_ws: bool, chain: NamedChain) -> String { return "https://mainnet.base.org".to_string(); } - let idx = next() % num_keys(); + let idx = next_idx() % (INFURA_KEYS.len() + ALCHEMY_KEYS.len()); let is_infura = idx < INFURA_KEYS.len(); let key = if is_infura { INFURA_KEYS[idx] } else { ALCHEMY_KEYS[idx - INFURA_KEYS.len()] }; From 2a194bd75a5d2477c3e8236dcdea64f4508e32ed Mon Sep 17 00:00:00 2001 From: Evan Chipman <42247026+evchip@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:49:10 +0700 Subject: [PATCH 51/58] Support EIP-7702 Delegations in Forge (#9236) * add EIP-7702 cheatcodes: createDelegation, signDelegation, attachDelegation * add cheatcode implementations for EIP-7702: createDelegationCall, signDelegationCall, attachDelegationCall; modify broadcast to check if sender has a delegation * add delegations hashmap to Cheatcodes struct * add revm crate * create AttachDelegationTest for EIP-7702 transactions * regen cheatcodes.json * cargo fmt * move broadcast under attachDelegation * combine createDelegationCall logic with signDelegationCall in order to create and sign delegation in a single call; remove delegation logic from broadcast() - no need to track delegations here * remove revm import from workspace * combine createDelegation logic inton signDelegation for simplicity * remove revm from forge script deps * combine createDelegation with signDelegation * WIP - refactor test to use SimpleDelegateContract and ERC20 - test currently failing bc 7702 implementation.execute not executed as Alice EOA * add logic to include authorization_list for EIP 7702 in TransactionRequest by searching delegations hash map by active_delegation * add address authority param to attachDelegation; remove nonce param from signDelegation, as it can be constructed in cheatcode. * remove 7702 tx request construction logic - now handled in attachDelegation cheatcode implementation * refactor attachDelegation cheatcode implementation to handle verifying signature and setting bytecode on EOA; refactor signDelegation cheatcode implementation to get nonce from signer * remove nonce param from attachDelegation cheatcode in favor of loading from authority account * refactor test to check for code on alice account and call execute on alice account through SimpleDelegateContract * revert refactor on TransactionRequest * format * cargo fmt * fix clippy errors * remove faulty logic comparing nonce to itself - nonce still checked by recovered signature * add more tests to cover revert cases on attachDelegation and multiple calls via delegation contract * cargo fmt * restore logic to check if there's an active delegation when building TransactionRequest; add fixed values for gas and max_priority_fee_per_gas to ensure tx success, with TODO comment to explain what's left * remove obsolete comment * add comments explaining delegations and active_delegation * cargo fmt * add logic to increase gas limit by PER_EMPTY_ACCOUNT_COST(25k) if tx includes authorization list for EIP 7702 tx, which is seemingly not accounted for in gas estimation; remove hardcoded gas values from call_with_executor * revert logic to add PER_EMPTY_ACCOUNT_COST for EIP 7702 txs - handled inside of revm now * remove manually setting transaction type to 4 if auth list is present - handled in revm * add method set_delegation to Executor for setting EIP-7702 authorization list in the transaction environment; call set_delegation from simulate_and_fill if auth list is not empty * remove redundancy with TransactionMaybeSigned var tx * cargo fmt * refactor: use authorization_list() helper to return authorization_list and set delegation * refactor: change Cheatcodes::active_delegation to Option and remove delegations hashmap - tx will only use one active delegation at a time, so no need for mapping * replace verbose logic to set bytecode on EOA with journaled_state.set_code helper * cargo fmt * increment nonce of authority account * add logic to set authorization_list to None if active_delegation is None * add test testSwitchDelegation to assert that attaching an additional delegation switches the implementation on the EOA * remove set_delegation logic in favor of adding call_raw_with_authorization - previous approach kept the delegation in the TxEnv, resulting in higher gas cost for all subsequent calls after the delegation was applied * refactor signDelegation to return struct SignedDelegation and for attachDelegation to accept SignedDelegation * update delegation tests to reflect change in cheatcode interface for signDelegation and attachDelegation * add cheatcode signAndAttachDelegation * add signAndAttachDelegationCall cheatcode logic; refactor helper methods for shared logic used in 7702 delegation cheatcodes * add test testCallSingleSignAndAttachDelegation for new cheatcode signAndAttachDelegation * add comments to SignedDelegation struct and cargo fmt * cargo fmt * fix ci * fix spec --------- Co-authored-by: Arsenii Kulikov Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> --- Cargo.lock | 1 + crates/cheatcodes/assets/cheatcodes.json | 91 +++++++++ crates/cheatcodes/spec/src/lib.rs | 1 + crates/cheatcodes/spec/src/vm.rs | 28 +++ crates/cheatcodes/src/inspector.rs | 39 ++-- crates/cheatcodes/src/script.rs | 89 +++++++++ crates/common/Cargo.toml | 1 + crates/common/src/transactions.rs | 9 + crates/evm/evm/src/executors/mod.rs | 19 +- crates/script/src/runner.rs | 26 ++- crates/script/src/simulate.rs | 5 +- testdata/cheats/Vm.sol | 4 + .../default/cheats/AttachDelegation.t.sol | 182 ++++++++++++++++++ 13 files changed, 477 insertions(+), 18 deletions(-) create mode 100644 testdata/default/cheats/AttachDelegation.t.sol diff --git a/Cargo.lock b/Cargo.lock index 144c6e078..6759a6d2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3701,6 +3701,7 @@ dependencies = [ "alloy-consensus", "alloy-contract", "alloy-dyn-abi", + "alloy-eips", "alloy-json-abi", "alloy-json-rpc", "alloy-primitives", diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 347d738e0..d19c776b9 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -573,6 +573,37 @@ "description": "Status of the transaction, retrieved from the transaction receipt." } ] + }, + { + "name": "SignedDelegation", + "description": "Holds a signed EIP-7702 authorization for an authority account to delegate to an implementation.", + "fields": [ + { + "name": "v", + "ty": "uint8", + "description": "The y-parity of the recovered secp256k1 signature (0 or 1)." + }, + { + "name": "r", + "ty": "bytes32", + "description": "First 32 bytes of the signature." + }, + { + "name": "s", + "ty": "bytes32", + "description": "Second 32 bytes of the signature." + }, + { + "name": "nonce", + "ty": "uint64", + "description": "The current nonce of the authority account at signing time.\n Used to ensure signature can't be replayed after account nonce changes." + }, + { + "name": "implementation", + "ty": "address", + "description": "Address of the contract implementation that will be delegated to.\n Gets encoded into delegation code: 0xef0100 || implementation." + } + ] } ], "cheatcodes": [ @@ -3076,6 +3107,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "attachDelegation", + "description": "Designate the next call as an EIP-7702 transaction", + "declaration": "function attachDelegation(SignedDelegation memory signedDelegation) external;", + "visibility": "external", + "mutability": "", + "signature": "attachDelegation((uint8,bytes32,bytes32,uint64,address))", + "selector": "0x14ae3519", + "selectorBytes": [ + 20, + 174, + 53, + 25 + ] + }, + "group": "scripting", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "blobBaseFee", @@ -8806,6 +8857,26 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "signAndAttachDelegation", + "description": "Sign an EIP-7702 authorization and designate the next call as an EIP-7702 transaction", + "declaration": "function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation);", + "visibility": "external", + "mutability": "", + "signature": "signAndAttachDelegation(address,uint256)", + "selector": "0xc7fa7288", + "selectorBytes": [ + 199, + 250, + 114, + 136 + ] + }, + "group": "scripting", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "signCompact_0", @@ -8886,6 +8957,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "signDelegation", + "description": "Sign an EIP-7702 authorization for delegation", + "declaration": "function signDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation);", + "visibility": "external", + "mutability": "", + "signature": "signDelegation(address,uint256)", + "selector": "0x5b593c7b", + "selectorBytes": [ + 91, + 89, + 60, + 123 + ] + }, + "group": "scripting", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "signP256", diff --git a/crates/cheatcodes/spec/src/lib.rs b/crates/cheatcodes/spec/src/lib.rs index 5692dfc48..c4d7e9868 100644 --- a/crates/cheatcodes/spec/src/lib.rs +++ b/crates/cheatcodes/spec/src/lib.rs @@ -87,6 +87,7 @@ impl Cheatcodes<'static> { Vm::Gas::STRUCT.clone(), Vm::DebugStep::STRUCT.clone(), Vm::BroadcastTxSummary::STRUCT.clone(), + Vm::SignedDelegation::STRUCT.clone(), ]), enums: Cow::Owned(vec![ Vm::CallerMode::ENUM.clone(), diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index d703f48e7..bf0fe9781 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -308,6 +308,22 @@ interface Vm { bool success; } + /// Holds a signed EIP-7702 authorization for an authority account to delegate to an implementation. + struct SignedDelegation { + /// The y-parity of the recovered secp256k1 signature (0 or 1). + uint8 v; + /// First 32 bytes of the signature. + bytes32 r; + /// Second 32 bytes of the signature. + bytes32 s; + /// The current nonce of the authority account at signing time. + /// Used to ensure signature can't be replayed after account nonce changes. + uint64 nonce; + /// Address of the contract implementation that will be delegated to. + /// Gets encoded into delegation code: 0xef0100 || implementation. + address implementation; + } + // ======== EVM ======== /// Gets the address for a given private key. @@ -2018,6 +2034,18 @@ interface Vm { #[cheatcode(group = Scripting)] function broadcastRawTransaction(bytes calldata data) external; + /// Sign an EIP-7702 authorization for delegation + #[cheatcode(group = Scripting)] + function signDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); + + /// Designate the next call as an EIP-7702 transaction + #[cheatcode(group = Scripting)] + function attachDelegation(SignedDelegation memory signedDelegation) external; + + /// Sign an EIP-7702 authorization and designate the next call as an EIP-7702 transaction + #[cheatcode(group = Scripting)] + function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); + /// Returns addresses of available unlocked wallets in the script environment. #[cheatcode(group = Scripting)] function getWallets() external returns (address[] memory wallets); diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 046a495a1..6f3acb58c 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -46,7 +46,10 @@ use revm::{ EOFCreateInputs, EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterAction, InterpreterResult, }, - primitives::{BlockEnv, CreateScheme, EVMError, EvmStorageSlot, SpecId, EOF_MAGIC_BYTES}, + primitives::{ + BlockEnv, CreateScheme, EVMError, EvmStorageSlot, SignedAuthorization, SpecId, + EOF_MAGIC_BYTES, + }, EvmContext, InnerEvmContext, Inspector, }; use serde_json::Value; @@ -373,6 +376,11 @@ pub struct Cheatcodes { /// execution block environment. pub block: Option, + /// Currently active EIP-7702 delegation that will be consumed when building the next + /// transaction. Set by `vm.attachDelegation()` and consumed via `.take()` during + /// transaction construction. + pub active_delegation: Option, + /// The gas price. /// /// Used in the cheatcode handler to overwrite the gas price separately from the gas price @@ -497,6 +505,7 @@ impl Cheatcodes { labels: config.labels.clone(), config, block: Default::default(), + active_delegation: Default::default(), gas_price: Default::default(), prank: Default::default(), expected_revert: Default::default(), @@ -1014,18 +1023,26 @@ where { let account = ecx.journaled_state.state().get_mut(&broadcast.new_origin).unwrap(); + let mut tx_req = TransactionRequest { + from: Some(broadcast.new_origin), + to: Some(TxKind::from(Some(call.target_address))), + value: call.transfer_value(), + input: TransactionInput::new(call.input.clone()), + nonce: Some(account.info.nonce), + chain_id: Some(ecx.env.cfg.chain_id), + gas: if is_fixed_gas_limit { Some(call.gas_limit) } else { None }, + ..Default::default() + }; + + if let Some(auth_list) = self.active_delegation.take() { + tx_req.authorization_list = Some(vec![auth_list]); + } else { + tx_req.authorization_list = None; + } + self.broadcastable_transactions.push_back(BroadcastableTransaction { rpc: ecx.db.active_fork_url(), - transaction: TransactionRequest { - from: Some(broadcast.new_origin), - to: Some(TxKind::from(Some(call.target_address))), - value: call.transfer_value(), - input: TransactionInput::new(call.input.clone()), - nonce: Some(account.info.nonce), - gas: if is_fixed_gas_limit { Some(call.gas_limit) } else { None }, - ..Default::default() - } - .into(), + transaction: tx_req.into(), }); debug!(target: "cheatcodes", tx=?self.broadcastable_transactions.back().unwrap(), "broadcastable call"); diff --git a/crates/cheatcodes/src/script.rs b/crates/cheatcodes/src/script.rs index 29a804efd..3e1239237 100644 --- a/crates/cheatcodes/src/script.rs +++ b/crates/cheatcodes/src/script.rs @@ -2,10 +2,13 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Address, B256, U256}; +use alloy_rpc_types::Authorization; +use alloy_signer::{Signature, SignerSync}; use alloy_signer_local::PrivateKeySigner; use alloy_sol_types::SolValue; use foundry_wallets::{multi_wallet::MultiWallet, WalletSigner}; use parking_lot::Mutex; +use revm::primitives::{Bytecode, SignedAuthorization}; use std::sync::Arc; impl Cheatcode for broadcast_0Call { @@ -29,6 +32,92 @@ impl Cheatcode for broadcast_2Call { } } +impl Cheatcode for attachDelegationCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { signedDelegation } = self; + let SignedDelegation { v, r, s, nonce, implementation } = signedDelegation; + + let auth = Authorization { + address: *implementation, + nonce: *nonce, + chain_id: ccx.ecx.env.cfg.chain_id, + }; + let signed_auth = SignedAuthorization::new_unchecked( + auth, + *v, + U256::from_be_bytes(r.0), + U256::from_be_bytes(s.0), + ); + write_delegation(ccx, signed_auth.clone())?; + ccx.state.active_delegation = Some(signed_auth); + Ok(Default::default()) + } +} + +impl Cheatcode for signDelegationCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { implementation, privateKey } = self; + let signer = PrivateKeySigner::from_bytes(&B256::from(*privateKey))?; + let authority = signer.address(); + let (auth, nonce) = create_auth(ccx, *implementation, authority)?; + let sig = signer.sign_hash_sync(&auth.signature_hash())?; + Ok(sig_to_delegation(sig, nonce, *implementation).abi_encode()) + } +} + +impl Cheatcode for signAndAttachDelegationCall { + fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { + let Self { implementation, privateKey } = self; + let signer = PrivateKeySigner::from_bytes(&B256::from(*privateKey))?; + let authority = signer.address(); + let (auth, nonce) = create_auth(ccx, *implementation, authority)?; + let sig = signer.sign_hash_sync(&auth.signature_hash())?; + let signed_auth = sig_to_auth(sig, auth); + write_delegation(ccx, signed_auth.clone())?; + ccx.state.active_delegation = Some(signed_auth); + Ok(sig_to_delegation(sig, nonce, *implementation).abi_encode()) + } +} + +fn create_auth( + ccx: &mut CheatsCtxt, + implementation: Address, + authority: Address, +) -> Result<(Authorization, u64)> { + let authority_acc = ccx.ecx.journaled_state.load_account(authority, &mut ccx.ecx.db)?; + let nonce = authority_acc.data.info.nonce; + Ok(( + Authorization { address: implementation, nonce, chain_id: ccx.ecx.env.cfg.chain_id }, + nonce, + )) +} + +fn write_delegation(ccx: &mut CheatsCtxt, auth: SignedAuthorization) -> Result<()> { + let authority = auth.recover_authority().map_err(|e| format!("{e}"))?; + let authority_acc = ccx.ecx.journaled_state.load_account(authority, &mut ccx.ecx.db)?; + if authority_acc.data.info.nonce != auth.nonce { + return Err("invalid nonce".into()); + } + authority_acc.data.info.nonce += 1; + let bytecode = Bytecode::new_eip7702(*auth.address()); + ccx.ecx.journaled_state.set_code(authority, bytecode); + Ok(()) +} + +fn sig_to_delegation(sig: Signature, nonce: u64, implementation: Address) -> SignedDelegation { + SignedDelegation { + v: sig.v().y_parity() as u8, + r: sig.r().into(), + s: sig.s().into(), + nonce, + implementation, + } +} + +fn sig_to_auth(sig: Signature, auth: Authorization) -> SignedAuthorization { + SignedAuthorization::new_unchecked(auth, sig.v().y_parity() as u8, sig.r(), sig.s()) +} + impl Cheatcode for startBroadcast_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml index 033c53e49..585e0080c 100644 --- a/crates/common/Cargo.toml +++ b/crates/common/Cargo.toml @@ -20,6 +20,7 @@ foundry-config.workspace = true alloy-contract.workspace = true alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] } +alloy-eips.workspace = true alloy-json-abi.workspace = true alloy-json-rpc.workspace = true alloy-primitives = { workspace = true, features = [ diff --git a/crates/common/src/transactions.rs b/crates/common/src/transactions.rs index 4ddef26dd..f0ed0b54f 100644 --- a/crates/common/src/transactions.rs +++ b/crates/common/src/transactions.rs @@ -1,6 +1,7 @@ //! Wrappers for transactions. use alloy_consensus::{Transaction, TxEnvelope}; +use alloy_eips::eip7702::SignedAuthorization; use alloy_primitives::{Address, TxKind, U256}; use alloy_provider::{ network::{AnyNetwork, ReceiptResponse, TransactionBuilder}, @@ -226,6 +227,14 @@ impl TransactionMaybeSigned { Self::Unsigned(tx) => tx.nonce, } } + + pub fn authorization_list(&self) -> Option> { + match self { + Self::Signed { tx, .. } => tx.authorization_list().map(|auths| auths.to_vec()), + Self::Unsigned(tx) => tx.authorization_list.as_deref().map(|auths| auths.to_vec()), + } + .filter(|auths| !auths.is_empty()) + } } impl From for TransactionMaybeSigned { diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 6f458258a..b5b31b812 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -31,8 +31,8 @@ use revm::{ db::{DatabaseCommit, DatabaseRef}, interpreter::{return_ok, InstructionResult}, primitives::{ - BlockEnv, Bytecode, Env, EnvWithHandlerCfg, ExecutionResult, Output, ResultAndState, - SpecId, TxEnv, TxKind, + AuthorizationList, BlockEnv, Bytecode, Env, EnvWithHandlerCfg, ExecutionResult, Output, + ResultAndState, SignedAuthorization, SpecId, TxEnv, TxKind, }, }; use std::borrow::Cow; @@ -378,6 +378,21 @@ impl Executor { self.call_with_env(env) } + /// Performs a raw call to an account on the current state of the VM with an EIP-7702 + /// authorization list. + pub fn call_raw_with_authorization( + &mut self, + from: Address, + to: Address, + calldata: Bytes, + value: U256, + authorization_list: Vec, + ) -> eyre::Result { + let mut env = self.build_test_env(from, to.into(), calldata, value); + env.tx.authorization_list = Some(AuthorizationList::Signed(authorization_list)); + self.call_with_env(env) + } + /// Performs a raw call to an account on the current state of the VM. pub fn transact_raw( &mut self, diff --git a/crates/script/src/runner.rs b/crates/script/src/runner.rs index a7d950690..fa8ff19d9 100644 --- a/crates/script/src/runner.rs +++ b/crates/script/src/runner.rs @@ -1,5 +1,6 @@ use super::ScriptResult; use crate::build::ScriptPredeployLibraries; +use alloy_eips::eip7702::SignedAuthorization; use alloy_primitives::{Address, Bytes, TxKind, U256}; use alloy_rpc_types::TransactionRequest; use eyre::Result; @@ -223,7 +224,7 @@ impl ScriptRunner { /// Executes the method that will collect all broadcastable transactions. pub fn script(&mut self, address: Address, calldata: Bytes) -> Result { - self.call(self.evm_opts.sender, address, calldata, U256::ZERO, false) + self.call(self.evm_opts.sender, address, calldata, U256::ZERO, None, false) } /// Runs a broadcastable transaction locally and persists its state. @@ -233,9 +234,17 @@ impl ScriptRunner { to: Option
, calldata: Option, value: Option, + authorization_list: Option>, ) -> Result { if let Some(to) = to { - self.call(from, to, calldata.unwrap_or_default(), value.unwrap_or(U256::ZERO), true) + self.call( + from, + to, + calldata.unwrap_or_default(), + value.unwrap_or(U256::ZERO), + authorization_list, + true, + ) } else if to.is_none() { let res = self.executor.deploy( from, @@ -282,9 +291,20 @@ impl ScriptRunner { to: Address, calldata: Bytes, value: U256, + authorization_list: Option>, commit: bool, ) -> Result { - let mut res = self.executor.call_raw(from, to, calldata.clone(), value)?; + let mut res = if let Some(authorization_list) = authorization_list { + self.executor.call_raw_with_authorization( + from, + to, + calldata.clone(), + value, + authorization_list, + )? + } else { + self.executor.call_raw(from, to, calldata.clone(), value)? + }; let mut gas_used = res.gas_used; // We should only need to calculate realistic gas costs when preparing to broadcast diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index a9798c43e..95427225f 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -112,10 +112,10 @@ impl PreSimulationState { // Executes all transactions from the different forks concurrently. let futs = transactions .into_iter() - .map(|transaction| async { + .map(|mut transaction| async { let mut runner = runners.get(&transaction.rpc).expect("invalid rpc url").write(); + let tx = transaction.tx_mut(); - let tx = transaction.tx(); let to = if let Some(TxKind::Call(to)) = tx.to() { Some(to) } else { None }; let result = runner .simulate( @@ -124,6 +124,7 @@ impl PreSimulationState { to, tx.input().map(Bytes::copy_from_slice), tx.value(), + tx.authorization_list(), ) .wrap_err("Internal EVM error during simulation")?; diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 2004c4456..9d1d3efd1 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -23,6 +23,7 @@ interface Vm { struct Gas { uint64 gasLimit; uint64 gasTotalUsed; uint64 gasMemoryUsed; int64 gasRefunded; uint64 gasRemaining; } struct DebugStep { uint256[] stack; bytes memoryInput; uint8 opcode; uint64 depth; bool isOutOfGas; address contractAddr; } struct BroadcastTxSummary { bytes32 txHash; BroadcastTxType txType; address contractAddress; uint64 blockNumber; bool success; } + struct SignedDelegation { uint8 v; bytes32 r; bytes32 s; uint64 nonce; address implementation; } function _expectCheatcodeRevert() external; function _expectCheatcodeRevert(bytes4 revertData) external; function _expectCheatcodeRevert(bytes calldata revertData) external; @@ -148,6 +149,7 @@ interface Vm { function assertTrue(bool condition, string calldata error) external pure; function assume(bool condition) external pure; function assumeNoRevert() external pure; + function attachDelegation(SignedDelegation memory signedDelegation) external; function blobBaseFee(uint256 newBlobBaseFee) external; function blobhashes(bytes32[] calldata hashes) external; function breakpoint(string calldata char) external pure; @@ -434,10 +436,12 @@ interface Vm { function setEnv(string calldata name, string calldata value) external; function setNonce(address account, uint64 newNonce) external; function setNonceUnsafe(address account, uint64 newNonce) external; + function signAndAttachDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); function signCompact(Wallet calldata wallet, bytes32 digest) external returns (bytes32 r, bytes32 vs); function signCompact(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signCompact(bytes32 digest) external pure returns (bytes32 r, bytes32 vs); function signCompact(address signer, bytes32 digest) external pure returns (bytes32 r, bytes32 vs); + function signDelegation(address implementation, uint256 privateKey) external returns (SignedDelegation memory signedDelegation); function signP256(uint256 privateKey, bytes32 digest) external pure returns (bytes32 r, bytes32 s); function sign(Wallet calldata wallet, bytes32 digest) external returns (uint8 v, bytes32 r, bytes32 s); function sign(uint256 privateKey, bytes32 digest) external pure returns (uint8 v, bytes32 r, bytes32 s); diff --git a/testdata/default/cheats/AttachDelegation.t.sol b/testdata/default/cheats/AttachDelegation.t.sol new file mode 100644 index 000000000..7befc9a32 --- /dev/null +++ b/testdata/default/cheats/AttachDelegation.t.sol @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity 0.8.18; + +import "ds-test/test.sol"; +import "cheats/Vm.sol"; + +contract AttachDelegationTest is DSTest { + event ExecutedBy(uint256 id); + + Vm constant vm = Vm(HEVM_ADDRESS); + uint256 alice_pk = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; + address payable alice = payable(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); + uint256 bob_pk = 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a; + address bob = 0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC; + + SimpleDelegateContract implementation; + SimpleDelegateContract implementation2; + ERC20 token; + + function setUp() public { + implementation = new SimpleDelegateContract(1); + implementation2 = new SimpleDelegateContract(2); + token = new ERC20(alice); + } + + function testCallSingleAttachDelegation() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + // executing as bob to make clear that we don't need to execute the tx as alice + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation); + + bytes memory code = address(alice).code; + require(code.length > 0, "no code written to alice"); + SimpleDelegateContract(alice).execute(calls); + + assertEq(token.balanceOf(bob), 100); + } + + function testMultiCallAttachDelegation() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation); + + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](2); + calls[0] = + SimpleDelegateContract.Call({to: address(token), data: abi.encodeCall(ERC20.mint, (50, bob)), value: 0}); + calls[1] = SimpleDelegateContract.Call({ + to: address(token), + data: abi.encodeCall(ERC20.mint, (50, address(this))), + value: 0 + }); + + SimpleDelegateContract(alice).execute(calls); + + assertEq(token.balanceOf(bob), 50); + assertEq(token.balanceOf(address(this)), 50); + } + + function testSwitchAttachDelegation() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation); + + vm.expectEmit(true, true, true, true); + emit ExecutedBy(1); + SimpleDelegateContract(alice).execute(calls); + + // switch to implementation2 + Vm.SignedDelegation memory signedDelegation2 = vm.signDelegation(address(implementation2), alice_pk); + vm.broadcast(bob_pk); + vm.attachDelegation(signedDelegation2); + + vm.expectEmit(true, true, true, true); + emit ExecutedBy(2); + SimpleDelegateContract(alice).execute(calls); + + // verify final state + assertEq(token.balanceOf(bob), 200); + } + + function testAttachDelegationRevertInvalidSignature() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + // change v from 1 to 0 + signedDelegation.v = (signedDelegation.v + 1) % 2; + vm.attachDelegation(signedDelegation); + + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + + vm.broadcast(alice_pk); + // empty revert because no bytecode was set to Alice's account + vm.expectRevert(); + SimpleDelegateContract(alice).execute(calls); + } + + function testAttachDelegationRevertsAfterNonceChange() public { + Vm.SignedDelegation memory signedDelegation = vm.signDelegation(address(implementation), alice_pk); + + vm.broadcast(alice_pk); + // send tx to increment alice's nonce + token.mint(1, bob); + + vm.expectRevert("vm.attachDelegation: invalid nonce"); + vm.attachDelegation(signedDelegation); + } + + function testCallSingleSignAndAttachDelegation() public { + SimpleDelegateContract.Call[] memory calls = new SimpleDelegateContract.Call[](1); + bytes memory data = abi.encodeCall(ERC20.mint, (100, bob)); + calls[0] = SimpleDelegateContract.Call({to: address(token), data: data, value: 0}); + vm.signAndAttachDelegation(address(implementation), alice_pk); + bytes memory code = address(alice).code; + require(code.length > 0, "no code written to alice"); + vm.broadcast(bob_pk); + SimpleDelegateContract(alice).execute(calls); + + assertEq(token.balanceOf(bob), 100); + } +} + +contract SimpleDelegateContract { + event Executed(address indexed to, uint256 value, bytes data); + event ExecutedBy(uint256 id); + + struct Call { + bytes data; + address to; + uint256 value; + } + + uint256 public immutable id; + + constructor(uint256 _id) { + id = _id; + } + + function execute(Call[] memory calls) external payable { + for (uint256 i = 0; i < calls.length; i++) { + Call memory call = calls[i]; + (bool success, bytes memory result) = call.to.call{value: call.value}(call.data); + require(success, string(result)); + emit Executed(call.to, call.value, call.data); + emit ExecutedBy(id); + } + } + + receive() external payable {} +} + +contract ERC20 { + address public minter; + mapping(address => uint256) private _balances; + + constructor(address _minter) { + minter = _minter; + } + + function mint(uint256 amount, address to) public { + _mint(to, amount); + } + + function balanceOf(address account) public view returns (uint256) { + return _balances[account]; + } + + function _mint(address account, uint256 amount) internal { + require(msg.sender == minter, "ERC20: msg.sender is not minter"); + require(account != address(0), "ERC20: mint to the zero address"); + unchecked { + _balances[account] += amount; + } + } +} From b9ee7de28ff7468a58eec811cb283e98c24fbecb Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:21:38 +0100 Subject: [PATCH 52/58] chore(deps): bump foundry-compilers 0.12.2 (#9364) --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6759a6d2f..189f2b222 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3766,9 +3766,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edf09554357ebfcd2ea28503badbaca311aac3c947d269a6bae5256543aa172" +checksum = "bb4df7894aa6a5371df998d3945a801e21daafaf5aa20541be8c25671768c984" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3804,9 +3804,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134b2499a20136716422f1ae5afd3a5d6c2ef833bf97b7c956285ca96c1d9743" +checksum = "732c9950ef23e96584e8b9f022562dbceb5b8d33dbb7a6ec033ee3b3e63d26e2" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3814,9 +3814,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a9be34b3a43e77871e5bbd75f4a81d23eebf8f098519ae1ae9e163a0f3d0da" +checksum = "b43d648a62b85344d1d7cc445541a2db6aa85b5acd971799f0cc3c18bbdf801b" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3838,9 +3838,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1738950051ebcee2135adac07b3ef1708c6377ffed0c5e9a2bb485f31498befb" +checksum = "167b634d89209acd6c28d9f4abd19e0d77e93a40595fb1c42dab7b4ca7a2bfe5" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3853,9 +3853,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac2d9982eedb0eb3819f82c7efa1e28c1f78e031cdfb6adfa34690364fe5e0d" +checksum = "dfe866840fe05f80cd105cd7f535f5c567a500a3dda80e70f6ebe8f149001544" dependencies = [ "alloy-primitives", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 624264cf2..2e52d1e59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -169,7 +169,7 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.9.0", default-features = false } -foundry-compilers = { version = "0.12.1", default-features = false } +foundry-compilers = { version = "0.12.2", default-features = false } foundry-fork-db = "0.6.0" solang-parser = "=0.3.3" From 622f922739923ed243b1b5d701bb9e0898b3ffee Mon Sep 17 00:00:00 2001 From: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:16:51 +0100 Subject: [PATCH 53/58] feat: rename `ShellOtps` to `GlobalOpts` (#9313) * rename ShellOpts to GlobalOpts * prefer arg / command over clap * add global opts * remove redundant GlobalOpts injection, only use where access to the global variables is required * add global thread pool * add try_jobs method for global rayon pool * limit unnecessary globalopts injection where shell::* is preferred * fix tests * port custom threads iterator to use global rayon thread pool * remove redundant ignores * remove leftover from merge conflict, fix clashing args with inlined global in nodeargs / anvil top level args * leftovers * add back global args in script args * fix unused global opts * ignore attempted multiple initializations of the global thread pool * add init, default spawn with default rayon settings on forge test * make test thread number configurable * add back max threads back test to reduce pressure * remove global --jobs rayon pool, revert to current implementation * fix import --- crates/anvil/src/anvil.rs | 11 +++++---- crates/cast/bin/args.rs | 9 +++---- crates/cast/bin/main.rs | 3 ++- crates/chisel/bin/main.rs | 12 ++++++---- crates/cli/src/opts/{shell.rs => global.rs} | 26 ++++++++++++++------- crates/cli/src/opts/mod.rs | 4 ++-- crates/common/src/io/shell.rs | 15 ++++++++++-- crates/forge/bin/cmd/create.rs | 8 +++---- crates/forge/bin/cmd/soldeer.rs | 1 - crates/forge/bin/cmd/test/mod.rs | 9 +++---- crates/forge/bin/main.rs | 2 +- crates/forge/bin/opts.rs | 9 +++---- crates/script/src/lib.rs | 9 +++---- crates/verify/src/bytecode.rs | 13 ++++++----- 14 files changed, 79 insertions(+), 52 deletions(-) rename crates/cli/src/opts/{shell.rs => global.rs} (80%) diff --git a/crates/anvil/src/anvil.rs b/crates/anvil/src/anvil.rs index 5e2a42f59..48e17ed44 100644 --- a/crates/anvil/src/anvil.rs +++ b/crates/anvil/src/anvil.rs @@ -3,7 +3,7 @@ use anvil::cmd::NodeArgs; use clap::{CommandFactory, Parser, Subcommand}; use eyre::Result; -use foundry_cli::{opts::ShellOpts, utils}; +use foundry_cli::{opts::GlobalOpts, utils}; #[cfg(all(feature = "jemalloc", unix))] #[global_allocator] @@ -13,14 +13,15 @@ static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; #[derive(Parser)] #[command(name = "anvil", version = anvil::VERSION_MESSAGE, next_display_order = None)] pub struct Anvil { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(flatten)] pub node: NodeArgs, #[command(subcommand)] pub cmd: Option, - - #[clap(flatten)] - pub shell: ShellOpts, } #[derive(Subcommand)] @@ -48,7 +49,7 @@ fn run() -> Result<()> { utils::load_dotenv(); let mut args = Anvil::parse(); - args.shell.shell().set(); + args.global.init()?; args.node.evm_opts.resolve_rpc_alias(); if let Some(cmd) = &args.cmd { diff --git a/crates/cast/bin/args.rs b/crates/cast/bin/args.rs index 8bb7f2d54..f010c279e 100644 --- a/crates/cast/bin/args.rs +++ b/crates/cast/bin/args.rs @@ -9,7 +9,7 @@ use alloy_primitives::{Address, B256, U256}; use alloy_rpc_types::BlockId; use clap::{Parser, Subcommand, ValueHint}; use eyre::Result; -use foundry_cli::opts::{EtherscanOpts, RpcOpts, ShellOpts}; +use foundry_cli::opts::{EtherscanOpts, GlobalOpts, RpcOpts}; use foundry_common::ens::NameOrAddress; use std::{path::PathBuf, str::FromStr}; @@ -31,11 +31,12 @@ const VERSION_MESSAGE: &str = concat!( next_display_order = None, )] pub struct Cast { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(subcommand)] pub cmd: CastSubcommand, - - #[clap(flatten)] - pub shell: ShellOpts, } #[derive(Subcommand)] diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index 2eac8682c..ffce79099 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -50,8 +50,9 @@ fn run() -> Result<()> { utils::load_dotenv(); utils::subscriber(); utils::enable_paint(); + let args = CastArgs::parse(); - args.shell.shell().set(); + args.global.init()?; main_args(args) } diff --git a/crates/chisel/bin/main.rs b/crates/chisel/bin/main.rs index dca99d4a5..acc2c6f17 100644 --- a/crates/chisel/bin/main.rs +++ b/crates/chisel/bin/main.rs @@ -11,7 +11,7 @@ use clap::{Parser, Subcommand}; use eyre::Context; use foundry_cli::{ handler, - opts::{CoreBuildArgs, ShellOpts}, + opts::{CoreBuildArgs, GlobalOpts}, utils::{self, LoadConfig}, }; use foundry_common::{evm::EvmArgs, fs}; @@ -50,12 +50,13 @@ const VERSION_MESSAGE: &str = concat!( #[derive(Debug, Parser)] #[command(name = "chisel", version = VERSION_MESSAGE)] pub struct Chisel { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(subcommand)] pub cmd: Option, - #[clap(flatten)] - pub shell: ShellOpts, - /// Path to a directory containing Solidity files to import, or path to a single Solidity file. /// /// These files will be evaluated before the top-level of the @@ -117,8 +118,9 @@ fn run() -> eyre::Result<()> { handler::install(); utils::subscriber(); utils::load_dotenv(); + let args = Chisel::parse(); - args.shell.shell().set(); + args.global.init()?; main_args(args) } diff --git a/crates/cli/src/opts/shell.rs b/crates/cli/src/opts/global.rs similarity index 80% rename from crates/cli/src/opts/shell.rs rename to crates/cli/src/opts/global.rs index e559cc0f2..99690a530 100644 --- a/crates/cli/src/opts/shell.rs +++ b/crates/cli/src/opts/global.rs @@ -1,11 +1,10 @@ use clap::{ArgAction, Parser}; use foundry_common::shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbosity}; +use serde::{Deserialize, Serialize}; -// note: `verbose` and `quiet` cannot have `short` because of conflicts with multiple commands. - -/// Global shell options. -#[derive(Clone, Copy, Debug, Default, Parser)] -pub struct ShellOpts { +/// Global options. +#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, Parser)] +pub struct GlobalOpts { /// Verbosity level of the log messages. /// /// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv). @@ -22,7 +21,7 @@ pub struct ShellOpts { /// Do not print log messages. #[clap(short, long, global = true, alias = "silent", help_heading = "Display options")] - pub quiet: bool, + quiet: bool, /// Format log messages as JSON. #[clap( @@ -32,14 +31,23 @@ pub struct ShellOpts { conflicts_with_all = &["quiet", "color"], help_heading = "Display options" )] - pub json: bool, + json: bool, /// The color of the log messages. #[clap(long, global = true, value_enum, help_heading = "Display options")] - pub color: Option, + color: Option, } -impl ShellOpts { +impl GlobalOpts { + /// Initialize the global options. + pub fn init(self) -> eyre::Result<()> { + // Set the global shell. + self.shell().set(); + + Ok(()) + } + + /// Create a new shell instance. pub fn shell(self) -> Shell { let mode = match self.quiet { true => OutputMode::Quiet, diff --git a/crates/cli/src/opts/mod.rs b/crates/cli/src/opts/mod.rs index 95bf9e126..4e5d35572 100644 --- a/crates/cli/src/opts/mod.rs +++ b/crates/cli/src/opts/mod.rs @@ -2,12 +2,12 @@ mod build; mod chain; mod dependency; mod ethereum; -mod shell; +mod global; mod transaction; pub use build::*; pub use chain::*; pub use dependency::*; pub use ethereum::*; -pub use shell::*; +pub use global::*; pub use transaction::*; diff --git a/crates/common/src/io/shell.rs b/crates/common/src/io/shell.rs index 09a167df9..fd667ea68 100644 --- a/crates/common/src/io/shell.rs +++ b/crates/common/src/io/shell.rs @@ -7,6 +7,7 @@ use anstream::AutoStream; use anstyle::Style; use clap::ValueEnum; use eyre::Result; +use serde::{Deserialize, Serialize}; use std::{ fmt, io::{prelude::*, IsTerminal}, @@ -34,7 +35,7 @@ pub fn is_quiet() -> bool { /// Returns whether the output format is [`OutputFormat::Json`]. pub fn is_json() -> bool { - Shell::get().output_format().is_json() + Shell::get().is_json() } /// The global shell instance. @@ -172,7 +173,7 @@ enum ShellOut { } /// Whether messages should use color output. -#[derive(Debug, Default, PartialEq, Clone, Copy, ValueEnum)] +#[derive(Debug, Default, PartialEq, Clone, Copy, Serialize, Deserialize, ValueEnum)] pub enum ColorChoice { /// Intelligently guess whether to use color output (default). #[default] @@ -262,6 +263,16 @@ impl Shell { self.needs_clear.swap(needs_clear, Ordering::Relaxed) } + /// Returns `true` if the output format is JSON. + pub fn is_json(&self) -> bool { + self.output_format.is_json() + } + + /// Returns `true` if the verbosity level is `Quiet`. + pub fn is_quiet(&self) -> bool { + self.output_mode.is_quiet() + } + /// Returns `true` if the `needs_clear` flag is set. #[inline] pub fn needs_clear(&self) -> bool { diff --git a/crates/forge/bin/cmd/create.rs b/crates/forge/bin/cmd/create.rs index e19feafcc..9fc2629e5 100644 --- a/crates/forge/bin/cmd/create.rs +++ b/crates/forge/bin/cmd/create.rs @@ -10,7 +10,7 @@ use alloy_signer::Signer; use alloy_transport::{Transport, TransportError}; use clap::{Parser, ValueHint}; use eyre::{Context, Result}; -use forge_verify::RetryArgs; +use forge_verify::{RetryArgs, VerifierArgs, VerifyArgs}; use foundry_cli::{ opts::{CoreBuildArgs, EthereumOpts, EtherscanOpts, TransactionOpts}, utils::{self, read_constructor_args_file, remove_contract, LoadConfig}, @@ -89,7 +89,7 @@ pub struct CreateArgs { eth: EthereumOpts, #[command(flatten)] - pub verifier: forge_verify::VerifierArgs, + pub verifier: VerifierArgs, #[command(flatten)] retry: RetryArgs, @@ -201,7 +201,7 @@ impl CreateArgs { ) -> Result<()> { // NOTE: this does not represent the same `VerifyArgs` that would be sent after deployment, // since we don't know the address yet. - let mut verify = forge_verify::VerifyArgs { + let mut verify = VerifyArgs { address: Default::default(), contract: Some(self.contract.clone()), compiler_version: Some(id.version.to_string()), @@ -359,7 +359,7 @@ impl CreateArgs { } else { None }; - let verify = forge_verify::VerifyArgs { + let verify = VerifyArgs { address, contract: Some(self.contract), compiler_version: Some(id.version.to_string()), diff --git a/crates/forge/bin/cmd/soldeer.rs b/crates/forge/bin/cmd/soldeer.rs index 56b8c31f3..b2c9a77f1 100644 --- a/crates/forge/bin/cmd/soldeer.rs +++ b/crates/forge/bin/cmd/soldeer.rs @@ -1,6 +1,5 @@ use clap::Parser; use eyre::Result; - use soldeer_commands::Command; // CLI arguments for `forge soldeer`. diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 4e811bcbf..435c34275 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -17,7 +17,7 @@ use forge::{ MultiContractRunner, MultiContractRunnerBuilder, TestFilter, TestOptions, TestOptionsBuilder, }; use foundry_cli::{ - opts::{CoreBuildArgs, ShellOpts}, + opts::{CoreBuildArgs, GlobalOpts}, utils::{self, LoadConfig}, }; use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs, shell, TestFunctionExt}; @@ -65,6 +65,10 @@ foundry_config::merge_impl_figment_convert!(TestArgs, opts, evm_opts); #[derive(Clone, Debug, Parser)] #[command(next_help_heading = "Test options")] pub struct TestArgs { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + /// The contract file you want to test, it's a shortcut for --match-path. #[arg(value_hint = ValueHint::FilePath)] pub path: Option, @@ -178,9 +182,6 @@ pub struct TestArgs { /// Print detailed test summary table. #[arg(long, help_heading = "Display options", requires = "summary")] pub detailed: bool, - - #[command(flatten)] - shell: ShellOpts, } impl TestArgs { diff --git a/crates/forge/bin/main.rs b/crates/forge/bin/main.rs index ee49f7f69..ac0992cf9 100644 --- a/crates/forge/bin/main.rs +++ b/crates/forge/bin/main.rs @@ -35,7 +35,7 @@ fn run() -> Result<()> { utils::enable_paint(); let args = Forge::parse(); - args.shell.shell().set(); + args.global.init()?; init_execution_context(&args.cmd); match args.cmd { diff --git a/crates/forge/bin/opts.rs b/crates/forge/bin/opts.rs index 39bc89e63..380cb61d4 100644 --- a/crates/forge/bin/opts.rs +++ b/crates/forge/bin/opts.rs @@ -8,7 +8,7 @@ use crate::cmd::{ use clap::{Parser, Subcommand, ValueHint}; use forge_script::ScriptArgs; use forge_verify::{VerifyArgs, VerifyBytecodeArgs, VerifyCheckArgs}; -use foundry_cli::opts::ShellOpts; +use foundry_cli::opts::GlobalOpts; use std::path::PathBuf; const VERSION_MESSAGE: &str = concat!( @@ -29,11 +29,12 @@ const VERSION_MESSAGE: &str = concat!( next_display_order = None, )] pub struct Forge { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + #[command(subcommand)] pub cmd: ForgeSubcommand, - - #[clap(flatten)] - pub shell: ShellOpts, } #[derive(Subcommand)] diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 180a09647..0f0283b9f 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -27,7 +27,7 @@ use eyre::{ContextCompat, Result}; use forge_script_sequence::{AdditionalContract, NestedValue}; use forge_verify::RetryArgs; use foundry_cli::{ - opts::{CoreBuildArgs, ShellOpts}, + opts::{CoreBuildArgs, GlobalOpts}, utils::LoadConfig, }; use foundry_common::{ @@ -78,6 +78,10 @@ foundry_config::merge_impl_figment_convert!(ScriptArgs, opts, evm_opts); /// CLI arguments for `forge script`. #[derive(Clone, Debug, Default, Parser)] pub struct ScriptArgs { + /// Include the global options. + #[command(flatten)] + pub global: GlobalOpts, + /// The contract you want to run. Either the file path or contract name. /// /// If multiple contracts exist in the same file you must specify the target contract with @@ -213,9 +217,6 @@ pub struct ScriptArgs { #[command(flatten)] pub retry: RetryArgs, - - #[clap(flatten)] - pub shell: ShellOpts, } impl ScriptArgs { diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index 0c3f9e5b0..cd86c4200 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -35,11 +35,11 @@ pub struct VerifyBytecodeArgs { pub contract: ContractInfo, /// The block at which the bytecode should be verified. - #[clap(long, value_name = "BLOCK")] + #[arg(long, value_name = "BLOCK")] pub block: Option, /// The constructor args to generate the creation code. - #[clap( + #[arg( long, num_args(1..), conflicts_with_all = &["constructor_args_path", "encoded_constructor_args"], @@ -65,14 +65,15 @@ pub struct VerifyBytecodeArgs { pub constructor_args_path: Option, /// The rpc url to use for verification. - #[clap(short = 'r', long, value_name = "RPC_URL", env = "ETH_RPC_URL")] + #[arg(short = 'r', long, value_name = "RPC_URL", env = "ETH_RPC_URL")] pub rpc_url: Option, - #[clap(flatten)] + /// Etherscan options. + #[command(flatten)] pub etherscan: EtherscanOpts, /// Verifier options. - #[clap(flatten)] + #[command(flatten)] pub verifier: VerifierArgs, /// The project's root path. @@ -83,7 +84,7 @@ pub struct VerifyBytecodeArgs { pub root: Option, /// Ignore verification for creation or runtime bytecode. - #[clap(long, value_name = "BYTECODE_TYPE")] + #[arg(long, value_name = "BYTECODE_TYPE")] pub ignore: Option, } From fb5f0e1c4d9b9b0861be3e3bd07963524c5ac08e Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:06:42 +0200 Subject: [PATCH 54/58] chore(deps): bump foundry-compilers 0.12.3 (#9368) --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 189f2b222..7451f42b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3766,9 +3766,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb4df7894aa6a5371df998d3945a801e21daafaf5aa20541be8c25671768c984" +checksum = "3a6131af72175c55aa531c4851290d9cf67af7a82b03f20a8a9d28dba81b9fd3" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3804,9 +3804,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732c9950ef23e96584e8b9f022562dbceb5b8d33dbb7a6ec033ee3b3e63d26e2" +checksum = "c522c473e7a111b81f0d47f8a65ca1ef0642c8c8d1ca2d1e230338210d16bb02" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -3814,9 +3814,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b43d648a62b85344d1d7cc445541a2db6aa85b5acd971799f0cc3c18bbdf801b" +checksum = "c7cd569a0c38d232244932e71933b54e418cddcc8f0c16fd8af96dd844b27788" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3838,9 +3838,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167b634d89209acd6c28d9f4abd19e0d77e93a40595fb1c42dab7b4ca7a2bfe5" +checksum = "3b80563ba10981ec4a9667fda9318d02721a81f248ae73303603388580150a35" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -3853,9 +3853,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfe866840fe05f80cd105cd7f535f5c567a500a3dda80e70f6ebe8f149001544" +checksum = "4a840a87cb4845d208df3390a12d3724e6d1cc1268a51ac334a01f80f9b6419b" dependencies = [ "alloy-primitives", "cfg-if", diff --git a/Cargo.toml b/Cargo.toml index 2e52d1e59..0cefa4cdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -169,7 +169,7 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.9.0", default-features = false } -foundry-compilers = { version = "0.12.2", default-features = false } +foundry-compilers = { version = "0.12.3", default-features = false } foundry-fork-db = "0.6.0" solang-parser = "=0.3.3" From 25cc1ac68b5f6977f23d713c01ec455ad7f03d21 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 21 Nov 2024 00:17:59 +0530 Subject: [PATCH 55/58] chore(deps): bump alloy 0.6.4 (#9280) * bump alloy to 0.6.1 * fix: ui - use AnyRpcBlock * fix: wallets - use PrimitveSig * bump 0.6.2 * replace: AnyNetworkBlock with AnyRpcBlock + HeaderResponse with BlockHeader * fix: configure_tx_env * fix: crypto cheatcodes * fix: anvil_core tx * fix * fix: verify-bytecode * fix cast + get_pretty_tx_attr * fix(`anvil`): core TypedTx + BlockListener task * fix * fix: anvil tests * fix: test_deser_block * fix: transaction_build * fix: test load state files * fix: deny.toml * fix: try_from AnyRpcTx to DepositTx + bump op-alloy types * bump * fix: configure_tx_env * fix: UiFmt * fix: vb * fix: common-fmt tests * nit * fix: sig encoding * fix: process deposit tx in transaction_build * fix: common-fmt tests * fix * Update deny.toml Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> * fixes * fix: use alloy impls for conversions * nit * fix: transaction_build * nit * fix: eip155 check and rm anvil core utils * clippy * nits * fix * nit * fix: impl UIfmt for TxEnvelope and AnyTxEnvelope * make header in pretty_block_basics exhaustive * clippy * fix * fix: txpool_content * fix * fix * fix overriding hashes * fix --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: grandizzy <38490174+grandizzy@users.noreply.github.com> --- Cargo.lock | 158 +++--- Cargo.toml | 54 +- crates/anvil/Cargo.toml | 2 +- crates/anvil/core/Cargo.toml | 6 +- crates/anvil/core/src/eth/mod.rs | 1 - crates/anvil/core/src/eth/transaction/mod.rs | 473 +++++----------- crates/anvil/core/src/eth/utils.rs | 13 - crates/anvil/src/config.rs | 35 +- crates/anvil/src/eth/api.rs | 87 ++- crates/anvil/src/eth/backend/db.rs | 4 +- crates/anvil/src/eth/backend/fork.rs | 43 +- crates/anvil/src/eth/backend/info.rs | 8 +- crates/anvil/src/eth/backend/mem/mod.rs | 273 ++++++---- crates/anvil/src/eth/error.rs | 5 + crates/anvil/src/eth/otterscan/api.rs | 57 +- crates/anvil/src/eth/pool/transactions.rs | 9 +- crates/anvil/src/eth/sign.rs | 2 +- crates/anvil/src/tasks/mod.rs | 10 +- .../test-data/state-dump-legacy-stress.json | 2 +- crates/anvil/test-data/state-dump-legacy.json | 2 +- crates/anvil/test-data/state-dump.json | 2 +- crates/anvil/tests/it/anvil_api.rs | 12 +- crates/anvil/tests/it/api.rs | 2 +- crates/anvil/tests/it/eip4844.rs | 18 +- crates/anvil/tests/it/eip7702.rs | 2 +- crates/anvil/tests/it/fork.rs | 4 +- crates/anvil/tests/it/ipc.rs | 2 +- crates/anvil/tests/it/logs.rs | 9 +- crates/anvil/tests/it/otterscan.rs | 5 +- crates/anvil/tests/it/pubsub.rs | 4 +- crates/anvil/tests/it/transaction.rs | 4 +- crates/cast/bin/cmd/creation_code.rs | 5 +- crates/cast/bin/cmd/run.rs | 31 +- crates/cast/src/lib.rs | 6 +- crates/cheatcodes/src/crypto.rs | 20 +- crates/cheatcodes/src/script.rs | 16 +- crates/common/fmt/src/ui.rs | 513 +++++++++++++----- crates/common/src/transactions.rs | 2 +- crates/evm/core/Cargo.toml | 3 +- crates/evm/core/src/backend/mod.rs | 29 +- crates/evm/core/src/fork/init.rs | 15 +- crates/evm/core/src/fork/multi.rs | 3 +- crates/evm/core/src/opts.rs | 5 +- crates/evm/core/src/utils.rs | 13 +- crates/verify/src/bytecode.rs | 81 ++- crates/verify/src/etherscan/mod.rs | 7 +- crates/verify/src/utils.rs | 15 +- crates/wallets/src/wallet_signer.rs | 18 +- 48 files changed, 1124 insertions(+), 966 deletions(-) delete mode 100644 crates/anvil/core/src/eth/utils.rs diff --git a/Cargo.lock b/Cargo.lock index 7451f42b7..ebc0c4e0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,9 +86,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ed961a48297c732a5d97ee321aa8bb5009ecadbcb077d8bec90cb54e651629" +checksum = "ae09ffd7c29062431dd86061deefe4e3c6f07fa0d674930095f8dcedb0baf02c" dependencies = [ "alloy-eips", "alloy-primitives", @@ -97,14 +97,15 @@ dependencies = [ "auto_impl", "c-kzg", "derive_more", + "k256", "serde", ] [[package]] name = "alloy-contract" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460ab80ce4bda1c80bcf96fe7460520476f2c7b734581c6567fac2708e2a60ef" +checksum = "66430a72d5bf5edead101c8c2f0a24bada5ec9f3cf9909b3e08b6d6899b4803e" dependencies = [ "alloy-dyn-abi", "alloy-json-abi", @@ -157,9 +158,9 @@ dependencies = [ [[package]] name = "alloy-eip7702" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ffc577390ce50234e02d841214b3dc0bea6aaaae8e04bbf3cb82e9a45da9eb" +checksum = "5f6cee6a35793f3db8a5ffe60e86c695f321d081a567211245f503e8c498fce8" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -172,9 +173,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b69e06cf9c37be824b9d26d6d101114fdde6af0c87de2828b414c05c4b3daa71" +checksum = "5b6aa3961694b30ba53d41006131a2fca3bdab22e4c344e46db2c639e7c2dfdd" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -190,9 +191,9 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde15e14944a88bd6a57d325e9a49b75558746fe16aaccc79713ae50a6a9574c" +checksum = "e53f7877ded3921d18a0a9556d55bedf84535567198c9edab2aa23106da91855" dependencies = [ "alloy-primitives", "alloy-serde", @@ -213,9 +214,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af5979e0d5a7bf9c7eb79749121e8256e59021af611322aee56e77e20776b4b3" +checksum = "3694b7e480728c0b3e228384f223937f14c10caef5a4c766021190fc8f283d35" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -227,9 +228,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "204237129086ce5dc17a58025e93739b01b45313841f98fa339eb1d780511e57" +checksum = "ea94b8ceb5c75d7df0a93ba0acc53b55a22b47b532b600a800a87ef04eb5b0b4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -243,14 +244,16 @@ dependencies = [ "async-trait", "auto_impl", "futures-utils-wasm", + "serde", + "serde_json", "thiserror 1.0.69", ] [[package]] name = "alloy-network-primitives" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514f70ee2a953db21631cd817b13a1571474ec77ddc03d47616d5e8203489fde" +checksum = "df9f3e281005943944d15ee8491534a1c7b3cbf7a7de26f8c433b842b93eb5f9" dependencies = [ "alloy-consensus", "alloy-eips", @@ -293,9 +296,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4814d141ede360bb6cd1b4b064f1aab9de391e7c4d0d4d50ac89ea4bc1e25fbd" +checksum = "40c1f9eede27bf4c13c099e8e64d54efd7ce80ef6ea47478aa75d5d74e2dba3b" dependencies = [ "alloy-chains", "alloy-consensus", @@ -335,9 +338,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba46eb69ddf7a9925b81f15229cb74658e6eebe5dd30a5b74e2cd040380573" +checksum = "90f1f34232f77341076541c405482e4ae12f0ee7153d8f9969fc1691201b2247" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -376,9 +379,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc2bd1e7403463a5f2c61e955bcc9d3072b63aa177442b0f9aa6a6d22a941e3" +checksum = "374dbe0dc3abdc2c964f36b3d3edf9cdb3db29d16bda34aa123f03d810bec1dd" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -402,9 +405,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea9bf1abdd506f985a53533f5ac01296bcd6102c5e139bbc5d40bc468d2c916" +checksum = "c74832aa474b670309c20fffc2a869fa141edab7c79ff7963fad0a08de60bae1" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -418,20 +421,21 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2382fc63fb0cf3e02818d547b80cb66cc49a31f8803d0c328402b2008bc13650" +checksum = "5ca97963132f78ddfc60e43a017348e6d52eea983925c23652f5b330e8e02291" dependencies = [ "alloy-primitives", + "alloy-rpc-types-eth", "alloy-serde", "serde", ] [[package]] name = "alloy-rpc-types-engine" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "886d22d41992287a235af2f3af4299b5ced2bcafb81eb835572ad35747476946" +checksum = "3f56294dce86af23ad6ee8df46cf8b0d292eb5d1ff67dc88a0886051e32b1faf" dependencies = [ "alloy-consensus", "alloy-eips", @@ -447,9 +451,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b034779a4850b4b03f5be5ea674a1cf7d746b2da762b34d1860ab45e48ca27" +checksum = "a8a477281940d82d29315846c7216db45b15e90bcd52309da9f54bcf7ad94a11" dependencies = [ "alloy-consensus", "alloy-eips", @@ -466,9 +470,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5fb6c5c401321f802f69dcdb95b932f30f8158f6798793f914baac5995628e" +checksum = "ecd8b4877ef520c138af702097477cdd19504a8e1e4675ba37e92ba40f2d3c6f" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -480,9 +484,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad066b49c3b1b5f64cdd2399177a19926a6a15db2dbf11e2098de621f9e7480" +checksum = "1d4ab49acf90a71f7fb894dc5fd485f1f07a1e348966c714c4d1e0b7478850a8" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -492,9 +496,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028e72eaa9703e4882344983cfe7636ce06d8cce104a78ea62fd19b46659efc4" +checksum = "4dfa4a7ccf15b2492bb68088692481fd6b2604ccbee1d0d6c44c21427ae4df83" dependencies = [ "alloy-primitives", "serde", @@ -503,9 +507,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "592c185d7100258c041afac51877660c7bf6213447999787197db4842f0e938e" +checksum = "2e10aec39d60dc27edcac447302c7803d2371946fb737245320a05b78eb2fafd" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -519,9 +523,9 @@ dependencies = [ [[package]] name = "alloy-signer-aws" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a406102908a4e51834f32c4e5c1b29aa2c407b3fd23a5cad129c28b56d85e1b8" +checksum = "0109e5b18079aec2a022e4bc9db1d74bcc046f8b66274ffa8b0e4322b44b2b44" dependencies = [ "alloy-consensus", "alloy-network", @@ -537,9 +541,9 @@ dependencies = [ [[package]] name = "alloy-signer-gcp" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8d363e12280cb43747d3b62a1e6f00d595bc1a56464bb20200c6b6ca5d68185" +checksum = "558651eb0d76bcf2224de694481e421112fa2cbc6fe6a413cc76fd67e14cf0d7" dependencies = [ "alloy-consensus", "alloy-network", @@ -555,9 +559,9 @@ dependencies = [ [[package]] name = "alloy-signer-ledger" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a642c9f66ac73ae0d5398ce7ce3ce5bdfad5658d549abd48ea48962e585dca" +checksum = "29781b6a064b6235de4ec3cc0810f59fe227b8d31258f23a077570fc9525d7a6" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -575,9 +579,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6614f02fc1d5b079b2a4a5320018317b506fd0a6d67c1fd5542a71201724986c" +checksum = "d8396f6dff60700bc1d215ee03d86ff56de268af96e2bf833a14d0bafcab9882" dependencies = [ "alloy-consensus", "alloy-network", @@ -594,9 +598,9 @@ dependencies = [ [[package]] name = "alloy-signer-trezor" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b754988ef4e1f5f7d55c132949bb2a10491ed6bbf1d35108269014f50da1823f" +checksum = "21267541177607141a5db6fd1abed5a46553b7a6d9363cf3d047721634705905" dependencies = [ "alloy-consensus", "alloy-network", @@ -684,9 +688,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be77579633ebbc1266ae6fd7694f75c408beb1aeb6865d0b18f22893c265a061" +checksum = "f99acddb34000d104961897dbb0240298e8b775a7efffb9fda2a1a3efedd65b3" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -704,9 +708,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fd1a5d0827939847983b46f2f79510361f901dc82f8e3c38ac7397af142c6e" +checksum = "5dc013132e34eeadaa0add7e74164c1503988bfba8bae885b32e0918ba85a8a6" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -719,9 +723,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8073d1186bfeeb8fbdd1292b6f1a0731f3aed8e21e1463905abfae0b96a887a6" +checksum = "063edc0660e81260653cc6a95777c29d54c2543a668aa5da2359fb450d25a1ba" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -740,9 +744,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.5.4" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61f27837bb4a1d6c83a28231c94493e814882f0e9058648a97e908a5f3fc9fcf" +checksum = "abd170e600801116d5efe64f74a4fc073dbbb35c807013a7d0a388742aeebba0" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -935,6 +939,7 @@ dependencies = [ "alloy-consensus", "alloy-dyn-abi", "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rpc-types", @@ -3972,13 +3977,14 @@ dependencies = [ name = "foundry-evm-core" version = "0.2.0" dependencies = [ + "alloy-consensus", "alloy-dyn-abi", "alloy-genesis", "alloy-json-abi", + "alloy-network", "alloy-primitives", "alloy-provider", "alloy-rpc-types", - "alloy-serde", "alloy-sol-types", "alloy-transport", "auto_impl", @@ -4072,10 +4078,11 @@ dependencies = [ [[package]] name = "foundry-fork-db" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fe4a1e7e0f122b28afc156681687249bd5cf910d9bf873efb1181e4d41fbc3" +checksum = "5fea8068a6b7929229f72059296da09bf3c1d15569fdb4a351d2983450587c12" dependencies = [ + "alloy-consensus", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -6271,9 +6278,9 @@ checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "op-alloy-consensus" -version = "0.5.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26c3b35b7b3e36d15e0563eebffe13c1d9ca16b7aaffcb6a64354633547e16b" +checksum = "bff54d1d790eca1f3aedbd666162e9c42eceff90b9f9d24b352ed9c2df1e901a" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6287,9 +6294,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.5.2" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bae9bf91b620e1e2c2291562e5998bc1247bd8ada011773e1997b31a95de99" +checksum = "981b7f8ab11fe85ba3c1723702f000429b8d0c16b5883c93d577895f262cbac6" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6297,6 +6304,7 @@ dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", "alloy-serde", + "derive_more", "op-alloy-consensus", "serde", "serde_json", @@ -7399,9 +7407,9 @@ dependencies = [ [[package]] name = "revm" -version = "17.1.0" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "055bee6a81aaeee8c2389ae31f0d4de87f44df24f4444a1116f9755fd87a76ad" +checksum = "15689a3c6a8d14b647b4666f2e236ef47b5a5133cdfd423f545947986fff7013" dependencies = [ "auto_impl", "cfg-if", @@ -7414,9 +7422,9 @@ dependencies = [ [[package]] name = "revm-inspectors" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e29c662f7887f3b659d4b0fd234673419a8fcbeaa1ecc29bf7034c0a75cc8ea" +checksum = "747291a18ad6726a08dd73f8b6a6b3a844db582ecae2063ccf0a04880c44f482" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -7432,9 +7440,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac2034454f8bc69dc7d3c94cdb1b57559e27f5ef0518771f1787de543d7d6a1" +checksum = "74e3f11d0fed049a4a10f79820c59113a79b38aed4ebec786a79d5c667bfeb51" dependencies = [ "revm-primitives", "serde", @@ -7442,9 +7450,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "14.0.0" +version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a88c8c7c5f9b988a9e65fc0990c6ce859cdb74114db705bd118a96d22d08027" +checksum = "e381060af24b750069a2b2d2c54bba273d84e8f5f9e8026fc9262298e26cc336" dependencies = [ "aurora-engine-modexp", "blst", @@ -7462,9 +7470,9 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d11fa1e195b0bebaf3fb18596f314a13ba3a4cb1fdd16d3465934d812fd921e" +checksum = "3702f132bb484f4f0d0ca4f6fbde3c82cfd745041abbedd6eda67730e1868ef0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -9761,9 +9769,9 @@ dependencies = [ [[package]] name = "wasmtimer" -version = "0.2.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7ed9d8b15c7fb594d72bfb4b5a276f3d2029333cd93a932f376f5937f6f80ee" +checksum = "bb4f099acbc1043cc752b91615b24b02d7f6fcd975bd781fed9f50b3c3e15bf7" dependencies = [ "futures", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index 0cefa4cdb..f5ec94b90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -170,39 +170,39 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.9.0", default-features = false } foundry-compilers = { version = "0.12.3", default-features = false } -foundry-fork-db = "0.6.0" +foundry-fork-db = "0.7.0" solang-parser = "=0.3.3" ## revm -revm = { version = "17.1.0", default-features = false } -revm-primitives = { version = "13.0.0", default-features = false } -revm-inspectors = { version = "0.10.0", features = ["serde"] } +revm = { version = "18.0.0", default-features = false } +revm-primitives = { version = "14.0.0", default-features = false } +revm-inspectors = { version = "0.11.0", features = ["serde"] } ## ethers ethers-contract-abigen = { version = "2.0.14", default-features = false } ## alloy -alloy-consensus = { version = "0.5.4", default-features = false } -alloy-contract = { version = "0.5.4", default-features = false } -alloy-eips = { version = "0.5.4", default-features = false } -alloy-genesis = { version = "0.5.4", default-features = false } -alloy-json-rpc = { version = "0.5.4", default-features = false } -alloy-network = { version = "0.5.4", default-features = false } -alloy-provider = { version = "0.5.4", default-features = false } -alloy-pubsub = { version = "0.5.4", default-features = false } -alloy-rpc-client = { version = "0.5.4", default-features = false } -alloy-rpc-types = { version = "0.5.4", default-features = true } -alloy-serde = { version = "0.5.4", default-features = false } -alloy-signer = { version = "0.5.4", default-features = false } -alloy-signer-aws = { version = "0.5.4", default-features = false } -alloy-signer-gcp = { version = "0.5.4", default-features = false } -alloy-signer-ledger = { version = "0.5.4", default-features = false } -alloy-signer-local = { version = "0.5.4", default-features = false } -alloy-signer-trezor = { version = "0.5.4", default-features = false } -alloy-transport = { version = "0.5.4", default-features = false } -alloy-transport-http = { version = "0.5.4", default-features = false } -alloy-transport-ipc = { version = "0.5.4", default-features = false } -alloy-transport-ws = { version = "0.5.4", default-features = false } +alloy-consensus = { version = "0.6.4", default-features = false } +alloy-contract = { version = "0.6.4", default-features = false } +alloy-eips = { version = "0.6.4", default-features = false } +alloy-genesis = { version = "0.6.4", default-features = false } +alloy-json-rpc = { version = "0.6.4", default-features = false } +alloy-network = { version = "0.6.4", default-features = false } +alloy-provider = { version = "0.6.4", default-features = false } +alloy-pubsub = { version = "0.6.4", default-features = false } +alloy-rpc-client = { version = "0.6.4", default-features = false } +alloy-rpc-types = { version = "0.6.4", default-features = true } +alloy-serde = { version = "0.6.4", default-features = false } +alloy-signer = { version = "0.6.4", default-features = false } +alloy-signer-aws = { version = "0.6.4", default-features = false } +alloy-signer-gcp = { version = "0.6.4", default-features = false } +alloy-signer-ledger = { version = "0.6.4", default-features = false } +alloy-signer-local = { version = "0.6.4", default-features = false } +alloy-signer-trezor = { version = "0.6.4", default-features = false } +alloy-transport = { version = "0.6.4", default-features = false } +alloy-transport-http = { version = "0.6.4", default-features = false } +alloy-transport-ipc = { version = "0.6.4", default-features = false } +alloy-transport-ws = { version = "0.6.4", default-features = false } ## alloy-core alloy-dyn-abi = "0.8.11" @@ -222,8 +222,8 @@ alloy-rlp = "0.3" alloy-trie = "0.6.0" ## op-alloy -op-alloy-rpc-types = "0.5.0" -op-alloy-consensus = "0.5.0" +op-alloy-rpc-types = "0.6.5" +op-alloy-consensus = "0.6.5" ## cli anstream = "0.6" diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 4c3cbc4f7..b3389d2ec 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -67,7 +67,7 @@ alloy-transport.workspace = true alloy-chains.workspace = true alloy-genesis.workspace = true alloy-trie.workspace = true -op-alloy-consensus.workspace = true +op-alloy-consensus = { workspace = true, features = ["serde"] } # axum related axum.workspace = true diff --git a/crates/anvil/core/Cargo.toml b/crates/anvil/core/Cargo.toml index dcf8bf508..dacc7f20e 100644 --- a/crates/anvil/core/Cargo.toml +++ b/crates/anvil/core/Cargo.toml @@ -22,7 +22,7 @@ revm = { workspace = true, default-features = false, features = [ "c-kzg", ] } -alloy-primitives = { workspace = true, features = ["serde"] } +alloy-primitives = { workspace = true, features = ["serde", "rlp"] } alloy-rpc-types = { workspace = true, features = ["anvil", "trace"] } alloy-serde.workspace = true alloy-rlp.workspace = true @@ -30,8 +30,8 @@ alloy-eips.workspace = true alloy-consensus = { workspace = true, features = ["k256", "kzg"] } alloy-dyn-abi = { workspace = true, features = ["std", "eip712"] } alloy-trie.workspace = true -op-alloy-consensus.workspace = true - +op-alloy-consensus = { workspace = true, features = ["serde"] } +alloy-network.workspace = true serde = { workspace = true, optional = true } serde_json.workspace = true bytes.workspace = true diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index 33ffda6a7..b1d3b8522 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -18,7 +18,6 @@ pub mod proof; pub mod subscription; pub mod transaction; pub mod trie; -pub mod utils; pub mod wallet; #[cfg(feature = "serde")] diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index 827f14a55..8de659799 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -6,22 +6,23 @@ use alloy_consensus::{ eip4844::{TxEip4844, TxEip4844Variant, TxEip4844WithSidecar}, TxEip7702, }, - AnyReceiptEnvelope, Receipt, ReceiptEnvelope, ReceiptWithBloom, Signed, TxEip1559, TxEip2930, - TxEnvelope, TxLegacy, TxReceipt, TxType, + AnyReceiptEnvelope, Receipt, ReceiptEnvelope, ReceiptWithBloom, Signed, Transaction, TxEip1559, + TxEip2930, TxEnvelope, TxLegacy, TxReceipt, }; use alloy_eips::eip2718::{Decodable2718, Eip2718Error, Encodable2718}; +use alloy_network::{AnyRpcTransaction, AnyTxEnvelope}; use alloy_primitives::{ - Address, Bloom, Bytes, Log, Parity, Signature, TxHash, TxKind, B256, U256, U64, + Address, Bloom, Bytes, Log, PrimitiveSignature, TxHash, TxKind, B256, U256, U64, }; use alloy_rlp::{length_of_length, Decodable, Encodable, Header}; use alloy_rpc_types::{ request::TransactionRequest, trace::otterscan::OtsReceipt, AccessList, AnyTransactionReceipt, - ConversionError, Signature as RpcSignature, Transaction as RpcTransaction, TransactionReceipt, + ConversionError, Transaction as RpcTransaction, TransactionReceipt, }; use alloy_serde::{OtherFields, WithOtherFields}; use bytes::BufMut; use foundry_evm::traces::CallTraceNode; -use op_alloy_consensus::TxDeposit; +use op_alloy_consensus::{TxDeposit, DEPOSIT_TX_TYPE_ID}; use revm::{ interpreter::InstructionResult, primitives::{OptimismFields, TxEnv}, @@ -278,162 +279,64 @@ pub fn to_alloy_transaction_with_hash_and_sender( from: Address, ) -> RpcTransaction { match transaction { - TypedTransaction::Legacy(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.tx().to.to().copied(), - value: t.tx().value, - gas_price: Some(t.tx().gas_price), - max_fee_per_gas: Some(t.tx().gas_price), - max_priority_fee_per_gas: Some(t.tx().gas_price), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: t.tx().chain_id, - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: None, - }), - access_list: None, - transaction_type: Some(0), - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, - TypedTransaction::EIP2930(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.tx().to.to().copied(), - value: t.tx().value, - gas_price: Some(t.tx().gas_price), - max_fee_per_gas: Some(t.tx().gas_price), - max_priority_fee_per_gas: Some(t.tx().gas_price), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: Some(t.tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().access_list.clone()), - transaction_type: Some(1), - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, - TypedTransaction::EIP1559(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.tx().to.to().copied(), - value: t.tx().value, - gas_price: None, - max_fee_per_gas: Some(t.tx().max_fee_per_gas), - max_priority_fee_per_gas: Some(t.tx().max_priority_fee_per_gas), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: Some(t.tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().access_list.clone()), - transaction_type: Some(2), - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, - TypedTransaction::EIP4844(t) => RpcTransaction { - hash, - nonce: t.tx().tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: Some(t.tx().tx().to), - value: t.tx().tx().value, - gas_price: Some(t.tx().tx().max_fee_per_gas), - max_fee_per_gas: Some(t.tx().tx().max_fee_per_gas), - max_priority_fee_per_gas: Some(t.tx().tx().max_priority_fee_per_gas), - gas: t.tx().tx().gas_limit, - input: t.tx().tx().input.clone(), - chain_id: Some(t.tx().tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().tx().access_list.clone()), - transaction_type: Some(3), - max_fee_per_blob_gas: Some(t.tx().tx().max_fee_per_blob_gas), - blob_versioned_hashes: Some(t.tx().tx().blob_versioned_hashes.clone()), - authorization_list: None, - }, - TypedTransaction::EIP7702(t) => RpcTransaction { - hash, - nonce: t.tx().nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: Some(t.tx().to), - value: t.tx().value, - gas_price: Some(t.tx().max_fee_per_gas), - max_fee_per_gas: Some(t.tx().max_fee_per_gas), - max_priority_fee_per_gas: Some(t.tx().max_priority_fee_per_gas), - gas: t.tx().gas_limit, - input: t.tx().input.clone(), - chain_id: Some(t.tx().chain_id), - signature: Some(RpcSignature { - r: t.signature().r(), - s: t.signature().s(), - v: U256::from(t.signature().v().to_u64()), - y_parity: Some(alloy_rpc_types::Parity::from(t.signature().v().y_parity())), - }), - access_list: Some(t.tx().access_list.clone()), - transaction_type: Some(4), - authorization_list: Some(t.tx().authorization_list.clone()), - ..Default::default() - }, - TypedTransaction::Deposit(t) => RpcTransaction { - hash, - nonce: t.nonce, - block_hash: None, - block_number: None, - transaction_index: None, - from, - to: t.kind.to().copied(), - value: t.value, - gas_price: None, - max_fee_per_gas: None, - max_priority_fee_per_gas: None, - gas: t.gas_limit, - input: t.input.clone().0.into(), - chain_id: t.chain_id().map(u64::from), - signature: None, - access_list: None, - transaction_type: None, - max_fee_per_blob_gas: None, - blob_versioned_hashes: None, - authorization_list: None, - }, + TypedTransaction::Legacy(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Legacy(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP2930(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip2930(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP1559(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip1559(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP4844(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip4844(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::EIP7702(t) => { + let (tx, sig, _) = t.into_parts(); + RpcTransaction { + block_hash: None, + block_number: None, + transaction_index: None, + from, + effective_gas_price: None, + inner: TxEnvelope::Eip7702(Signed::new_unchecked(tx, sig, hash)), + } + } + TypedTransaction::Deposit(_t) => { + unreachable!("cannot reach here, handled in `transaction_build` ") + } } } @@ -681,7 +584,8 @@ impl TryFrom for TransactionRequest { type Error = ConversionError; fn try_from(value: TypedTransaction) -> Result { - let from = value.recover().map_err(|_| ConversionError::InvalidSignature)?; + let from = + value.recover().map_err(|_| ConversionError::Custom("InvalidSignature".to_string()))?; let essentials = value.essentials(); let tx_type = value.r#type(); Ok(Self { @@ -702,8 +606,77 @@ impl TryFrom for TransactionRequest { } } +impl TryFrom for TypedTransaction { + type Error = ConversionError; + + fn try_from(value: AnyRpcTransaction) -> Result { + let AnyRpcTransaction { inner, .. } = value; + let from = inner.from; + match inner.inner { + AnyTxEnvelope::Ethereum(tx) => match tx { + TxEnvelope::Legacy(tx) => Ok(Self::Legacy(tx)), + TxEnvelope::Eip2930(tx) => Ok(Self::EIP2930(tx)), + TxEnvelope::Eip1559(tx) => Ok(Self::EIP1559(tx)), + TxEnvelope::Eip4844(tx) => Ok(Self::EIP4844(tx)), + TxEnvelope::Eip7702(tx) => Ok(Self::EIP7702(tx)), + _ => Err(ConversionError::Custom("UnsupportedTxType".to_string())), + }, + AnyTxEnvelope::Unknown(mut tx) => { + // Try to convert to deposit transaction + if tx.ty() == DEPOSIT_TX_TYPE_ID { + let nonce = get_field::(&tx.inner.fields, "nonce")?; + tx.inner.fields.insert("from".to_string(), serde_json::to_value(from).unwrap()); + let deposit_tx = + tx.inner.fields.deserialize_into::().map_err(|e| { + ConversionError::Custom(format!( + "Failed to deserialize deposit tx: {e}" + )) + })?; + + let TxDeposit { + source_hash, + is_system_transaction, + value, + gas_limit, + input, + mint, + from, + to, + } = deposit_tx; + + let deposit_tx = DepositTransaction { + nonce: nonce.to(), + source_hash, + from, + kind: to, + mint: mint.map(|m| U256::from(m)).unwrap_or_default(), + value, + gas_limit, + is_system_tx: is_system_transaction, + input, + }; + + return Ok(Self::Deposit(deposit_tx)); + }; + + Err(ConversionError::Custom("UnknownTxType".to_string())) + } + } + } +} + +fn get_field( + fields: &OtherFields, + key: &str, +) -> Result { + fields + .get_deserialized::(key) + .ok_or_else(|| ConversionError::Custom(format!("Missing{key}")))? + .map_err(|e| ConversionError::Custom(format!("Failed to deserialize {key}: {e}"))) +} + impl TypedTransaction { - /// Returns true if the transaction uses dynamic fees: EIP1559 or EIP4844 + /// Returns true if the transaction uses dynamic fees: EIP1559, EIP4844 or EIP7702 pub fn is_dynamic_fee(&self) -> bool { matches!(self, Self::EIP1559(_) | Self::EIP4844(_) | Self::EIP7702(_)) } @@ -992,168 +965,18 @@ impl TypedTransaction { } /// Returns the Signature of the transaction - pub fn signature(&self) -> Signature { + pub fn signature(&self) -> PrimitiveSignature { match self { Self::Legacy(tx) => *tx.signature(), Self::EIP2930(tx) => *tx.signature(), Self::EIP1559(tx) => *tx.signature(), Self::EIP4844(tx) => *tx.signature(), Self::EIP7702(tx) => *tx.signature(), - Self::Deposit(_) => Signature::from_scalars_and_parity( + Self::Deposit(_) => PrimitiveSignature::from_scalars_and_parity( B256::with_last_byte(1), B256::with_last_byte(1), - Parity::Parity(false), - ) - .unwrap(), - } - } -} - -impl TryFrom> for TypedTransaction { - type Error = ConversionError; - - fn try_from(tx: WithOtherFields) -> Result { - if tx.transaction_type.is_some_and(|t| t == 0x7E) { - let mint = tx - .other - .get_deserialized::("mint") - .ok_or(ConversionError::Custom("MissingMint".to_string()))? - .map_err(|_| ConversionError::Custom("Cannot deserialize mint".to_string()))?; - - let source_hash = tx - .other - .get_deserialized::("sourceHash") - .ok_or(ConversionError::Custom("MissingSourceHash".to_string()))? - .map_err(|_| { - ConversionError::Custom("Cannot deserialize source hash".to_string()) - })?; - - let deposit = DepositTransaction { - nonce: tx.nonce, - is_system_tx: true, - from: tx.from, - kind: tx.to.map(TxKind::Call).unwrap_or(TxKind::Create), - value: tx.value, - gas_limit: tx.gas, - input: tx.input.clone(), - mint, - source_hash, - }; - - return Ok(Self::Deposit(deposit)); - } - - let tx = tx.inner; - match tx.transaction_type.unwrap_or_default().try_into()? { - TxType::Legacy => { - let legacy = TxLegacy { - chain_id: tx.chain_id, - nonce: tx.nonce, - gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - gas_limit: tx.gas, - value: tx.value, - input: tx.input, - to: tx.to.map_or(TxKind::Create, TxKind::Call), - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::Legacy(Signed::new_unchecked(legacy, signature, tx.hash))) - } - TxType::Eip1559 => { - let eip1559 = TxEip1559 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - max_fee_per_gas: tx - .max_fee_per_gas - .ok_or(ConversionError::MissingMaxFeePerGas)?, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, - gas_limit: tx.gas, - value: tx.value, - input: tx.input, - to: tx.to.map_or(TxKind::Create, TxKind::Call), - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::EIP1559(Signed::new_unchecked(eip1559, signature, tx.hash))) - } - TxType::Eip2930 => { - let eip2930 = TxEip2930 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - gas_price: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - gas_limit: tx.gas, - value: tx.value, - input: tx.input, - to: tx.to.map_or(TxKind::Create, TxKind::Call), - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::EIP2930(Signed::new_unchecked(eip2930, signature, tx.hash))) - } - TxType::Eip4844 => { - let eip4844 = TxEip4844 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - gas_limit: tx.gas, - max_fee_per_gas: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, - max_fee_per_blob_gas: tx - .max_fee_per_blob_gas - .ok_or(ConversionError::MissingMaxFeePerBlobGas)?, - to: tx.to.ok_or(ConversionError::MissingTo)?, - value: tx.value, - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - blob_versioned_hashes: tx - .blob_versioned_hashes - .ok_or(ConversionError::MissingBlobVersionedHashes)?, - input: tx.input, - }; - Ok(Self::EIP4844(Signed::new_unchecked( - TxEip4844Variant::TxEip4844(eip4844), - tx.signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?, - tx.hash, - ))) - } - TxType::Eip7702 => { - let eip7702 = TxEip7702 { - chain_id: tx.chain_id.ok_or(ConversionError::MissingChainId)?, - nonce: tx.nonce, - gas_limit: tx.gas, - max_fee_per_gas: tx.gas_price.ok_or(ConversionError::MissingGasPrice)?, - max_priority_fee_per_gas: tx - .max_priority_fee_per_gas - .ok_or(ConversionError::MissingMaxPriorityFeePerGas)?, - to: tx.to.ok_or(ConversionError::MissingTo)?, - value: tx.value, - access_list: tx.access_list.ok_or(ConversionError::MissingAccessList)?, - input: tx.input, - authorization_list: tx.authorization_list.unwrap_or_default(), - }; - let signature = tx - .signature - .ok_or(ConversionError::MissingSignature)? - .try_into() - .map_err(ConversionError::SignatureError)?; - Ok(Self::EIP7702(Signed::new_unchecked(eip7702, signature, tx.hash))) - } + false, + ), } } } @@ -1200,10 +1023,7 @@ impl Encodable2718 for TypedTransaction { Self::EIP2930(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), Self::EIP1559(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), Self::EIP4844(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), - Self::EIP7702(tx) => { - let payload_length = tx.tx().fields_len() + tx.signature().rlp_vrs_len(); - Header { list: true, payload_length }.length() + payload_length + 1 - } + Self::EIP7702(tx) => TxEnvelope::from(tx.clone()).encode_2718_len(), Self::Deposit(tx) => 1 + tx.length(), } } @@ -1214,7 +1034,7 @@ impl Encodable2718 for TypedTransaction { Self::EIP2930(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), Self::EIP1559(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), Self::EIP4844(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), - Self::EIP7702(tx) => tx.tx().encode_with_signature(tx.signature(), out, false), + Self::EIP7702(tx) => TxEnvelope::from(tx.clone()).encode_2718(out), Self::Deposit(tx) => { tx.encode_2718(out); } @@ -1224,15 +1044,14 @@ impl Encodable2718 for TypedTransaction { impl Decodable2718 for TypedTransaction { fn typed_decode(ty: u8, buf: &mut &[u8]) -> Result { - match ty { - 0x04 => return Ok(Self::EIP7702(TxEip7702::decode_signed_fields(buf)?)), - 0x7E => return Ok(Self::Deposit(DepositTransaction::decode(buf)?)), - _ => {} + if ty == 0x7E { + return Ok(Self::Deposit(DepositTransaction::decode(buf)?)) } match TxEnvelope::typed_decode(ty, buf)? { TxEnvelope::Eip2930(tx) => Ok(Self::EIP2930(tx)), TxEnvelope::Eip1559(tx) => Ok(Self::EIP1559(tx)), TxEnvelope::Eip4844(tx) => Ok(Self::EIP4844(tx)), + TxEnvelope::Eip7702(tx) => Ok(Self::EIP7702(tx)), _ => unreachable!(), } } @@ -1703,7 +1522,7 @@ mod tests { chain_id: Some(4), }; - let signature = Signature::from_str("0eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca182b").unwrap(); + let signature = PrimitiveSignature::from_str("0eb96ca19e8a77102767a41fc85a36afd5c61ccb09911cec5d3e86e193d9c5ae3a456401896b1b6055311536bf00a718568c744d8c1f9df59879e8350220ca182b").unwrap(); let tx = TypedTransaction::Legacy(Signed::new_unchecked( tx, diff --git a/crates/anvil/core/src/eth/utils.rs b/crates/anvil/core/src/eth/utils.rs deleted file mode 100644 index a60439280..000000000 --- a/crates/anvil/core/src/eth/utils.rs +++ /dev/null @@ -1,13 +0,0 @@ -use alloy_primitives::Parity; - -/// See -/// > If you do, then the v of the signature MUST be set to {0,1} + CHAIN_ID * 2 + 35 where -/// > {0,1} is the parity of the y value of the curve point for which r is the x-value in the -/// > secp256k1 signing process. -pub fn meets_eip155(chain_id: u64, v: Parity) -> bool { - let double_chain_id = chain_id.saturating_mul(2); - match v { - Parity::Eip155(v) => v == double_chain_id + 35 || v == double_chain_id + 36, - _ => false, - } -} diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index 556175818..714f91e6d 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -15,12 +15,12 @@ use crate::{ mem::{self, in_memory_db::MemDb}, EthereumHardfork, FeeManager, PrecompileFactory, }; +use alloy_consensus::BlockHeader; use alloy_genesis::Genesis; -use alloy_network::AnyNetwork; +use alloy_network::{AnyNetwork, TransactionResponse}; use alloy_primitives::{hex, map::HashMap, utils::Unit, BlockNumber, TxHash, U256}; use alloy_provider::Provider; -use alloy_rpc_types::{Block, BlockNumberOrTag, Transaction}; -use alloy_serde::WithOtherFields; +use alloy_rpc_types::{Block, BlockNumberOrTag}; use alloy_signer::Signer; use alloy_signer_local::{ coins_bip39::{English, Mnemonic}, @@ -1291,12 +1291,15 @@ latest block number: {latest_block}" /// we only use the gas limit value of the block if it is non-zero and the block gas /// limit is enabled, since there are networks where this is not used and is always /// `0x0` which would inevitably result in `OutOfGas` errors as soon as the evm is about to record gas, See also - pub(crate) fn fork_gas_limit(&self, block: &Block>) -> u128 { + pub(crate) fn fork_gas_limit( + &self, + block: &Block, + ) -> u128 { if !self.disable_block_gas_limit { if let Some(gas_limit) = self.gas_limit { return gas_limit; - } else if block.header.gas_limit > 0 { - return block.header.gas_limit as u128; + } else if block.header.gas_limit() > 0 { + return block.header.gas_limit() as u128; } } @@ -1335,19 +1338,21 @@ async fn derive_block_and_transactions( // Get the block pertaining to the fork transaction let transaction_block = provider - .get_block_by_number(transaction_block_number.into(), true) + .get_block_by_number( + transaction_block_number.into(), + alloy_rpc_types::BlockTransactionsKind::Full, + ) .await? .ok_or(eyre::eyre!("Failed to get fork block by number"))?; // Filter out transactions that are after the fork transaction - let filtered_transactions: Vec<&alloy_serde::WithOtherFields> = - transaction_block - .transactions - .as_transactions() - .ok_or(eyre::eyre!("Failed to get transactions from full fork block"))? - .iter() - .take_while_inclusive(|&transaction| transaction.hash != transaction_hash.0) - .collect(); + let filtered_transactions = transaction_block + .transactions + .as_transactions() + .ok_or(eyre::eyre!("Failed to get transactions from full fork block"))? + .iter() + .take_while_inclusive(|&transaction| transaction.tx_hash() != transaction_hash.0) + .collect::>(); // Convert the transactions to PoolTransactions let force_transactions = filtered_transactions diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 6ee7c6d60..daf9dc4a0 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -30,15 +30,16 @@ use crate::{ revm::primitives::{BlobExcessGasAndPrice, Output}, ClientFork, LoggingManager, Miner, MiningMode, StorageInfo, }; -use alloy_consensus::{transaction::eip4844::TxEip4844Variant, Account, TxEnvelope}; +use alloy_consensus::{transaction::eip4844::TxEip4844Variant, Account}; use alloy_dyn_abi::TypedData; use alloy_eips::eip2718::Encodable2718; use alloy_network::{ - eip2718::Decodable2718, BlockResponse, Ethereum, NetworkWallet, TransactionBuilder, + eip2718::Decodable2718, AnyRpcBlock, AnyRpcTransaction, BlockResponse, Ethereum, NetworkWallet, + TransactionBuilder, TransactionResponse, }; use alloy_primitives::{ map::{HashMap, HashSet}, - Address, Bytes, Parity, TxHash, TxKind, B256, B64, U256, U64, + Address, Bytes, PrimitiveSignature as Signature, TxHash, TxKind, B256, B64, U256, U64, }; use alloy_provider::utils::{ eip1559_default_estimator, EIP1559_FEE_ESTIMATION_PAST_BLOCKS, @@ -56,12 +57,10 @@ use alloy_rpc_types::{ parity::LocalizedTransactionTrace, }, txpool::{TxpoolContent, TxpoolInspect, TxpoolInspectSummary, TxpoolStatus}, - AccessList, AccessListResult, AnyNetworkBlock, BlockId, BlockNumberOrTag as BlockNumber, - BlockTransactions, EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, - Transaction, + AccessList, AccessListResult, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, + EIP1186AccountProofResponse, FeeHistory, Filter, FilteredParams, Index, Log, }; use alloy_serde::WithOtherFields; -use alloy_signer::Signature; use alloy_transport::TransportErrorKind; use anvil_core::{ eth::{ @@ -475,13 +474,11 @@ impl EthApi { ) -> Result { match request { TypedTransactionRequest::Deposit(_) => { - let nil_signature: alloy_primitives::Signature = - alloy_primitives::Signature::from_scalars_and_parity( - B256::with_last_byte(1), - B256::with_last_byte(1), - Parity::Parity(false), - ) - .unwrap(); + let nil_signature = Signature::from_scalars_and_parity( + B256::with_last_byte(1), + B256::with_last_byte(1), + false, + ); return build_typed_transaction(request, nil_signature) } _ => { @@ -514,10 +511,7 @@ impl EthApi { match self.pool.get_transaction(hash) { Some(tx) => Ok(Some(tx.transaction.encoded_2718().into())), None => match self.backend.transaction_by_hash(hash).await? { - Some(tx) => TxEnvelope::try_from(tx.inner) - .map_or(Err(BlockchainError::FailedToDecodeTransaction), |tx| { - Ok(Some(tx.encoded_2718().into())) - }), + Some(tx) => Ok(Some(tx.inner.inner.encoded_2718().into())), None => Ok(None), }, } @@ -742,7 +736,7 @@ impl EthApi { /// Returns block with given hash. /// /// Handler for ETH RPC call: `eth_getBlockByHash` - pub async fn block_by_hash(&self, hash: B256) -> Result> { + pub async fn block_by_hash(&self, hash: B256) -> Result> { node_info!("eth_getBlockByHash"); self.backend.block_by_hash(hash).await } @@ -750,7 +744,7 @@ impl EthApi { /// Returns a _full_ block with given hash. /// /// Handler for ETH RPC call: `eth_getBlockByHash` - pub async fn block_by_hash_full(&self, hash: B256) -> Result> { + pub async fn block_by_hash_full(&self, hash: B256) -> Result> { node_info!("eth_getBlockByHash"); self.backend.block_by_hash_full(hash).await } @@ -758,7 +752,7 @@ impl EthApi { /// Returns block with given number. /// /// Handler for ETH RPC call: `eth_getBlockByNumber` - pub async fn block_by_number(&self, number: BlockNumber) -> Result> { + pub async fn block_by_number(&self, number: BlockNumber) -> Result> { node_info!("eth_getBlockByNumber"); if number == BlockNumber::Pending { return Ok(Some(self.pending_block().await)); @@ -770,10 +764,7 @@ impl EthApi { /// Returns a _full_ block with given number /// /// Handler for ETH RPC call: `eth_getBlockByNumber` - pub async fn block_by_number_full( - &self, - number: BlockNumber, - ) -> Result> { + pub async fn block_by_number_full(&self, number: BlockNumber) -> Result> { node_info!("eth_getBlockByNumber"); if number == BlockNumber::Pending { return Ok(self.pending_block_full().await); @@ -1185,10 +1176,7 @@ impl EthApi { /// this will also scan the mempool for a matching pending transaction /// /// Handler for ETH RPC call: `eth_getTransactionByHash` - pub async fn transaction_by_hash( - &self, - hash: B256, - ) -> Result>> { + pub async fn transaction_by_hash(&self, hash: B256) -> Result> { node_info!("eth_getTransactionByHash"); let mut tx = self.pool.get_transaction(hash).map(|pending| { let from = *pending.sender(); @@ -1218,7 +1206,7 @@ impl EthApi { &self, hash: B256, index: Index, - ) -> Result>> { + ) -> Result> { node_info!("eth_getTransactionByBlockHashAndIndex"); self.backend.transaction_by_block_hash_and_index(hash, index).await } @@ -1230,7 +1218,7 @@ impl EthApi { &self, block: BlockNumber, idx: Index, - ) -> Result>> { + ) -> Result> { node_info!("eth_getTransactionByBlockNumberAndIndex"); self.backend.transaction_by_block_number_and_index(block, idx).await } @@ -1262,7 +1250,7 @@ impl EthApi { &self, block_hash: B256, idx: Index, - ) -> Result> { + ) -> Result> { node_info!("eth_getUncleByBlockHashAndIndex"); let number = self.backend.ensure_block_number(Some(BlockId::Hash(block_hash.into()))).await?; @@ -1282,7 +1270,7 @@ impl EthApi { &self, block_number: BlockNumber, idx: Index, - ) -> Result> { + ) -> Result> { node_info!("eth_getUncleByBlockNumberAndIndex"); let number = self.backend.ensure_block_number(Some(BlockId::Number(block_number))).await?; if let Some(fork) = self.get_fork() { @@ -1544,7 +1532,7 @@ impl EthApi { ) -> Result> { node_info!("eth_getRawTransactionByBlockHashAndIndex"); match self.backend.transaction_by_block_hash_and_index(block_hash, index).await? { - Some(tx) => self.inner_raw_transaction(tx.hash).await, + Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await, None => Ok(None), } } @@ -1559,7 +1547,7 @@ impl EthApi { ) -> Result> { node_info!("eth_getRawTransactionByBlockNumberAndIndex"); match self.backend.transaction_by_block_number_and_index(block_number, index).await? { - Some(tx) => self.inner_raw_transaction(tx.hash).await, + Some(tx) => self.inner_raw_transaction(tx.tx_hash()).await, None => Ok(None), } } @@ -2175,10 +2163,7 @@ impl EthApi { /// **Note**: This behaves exactly as [Self::evm_mine] but returns different output, for /// compatibility reasons, this is a separate call since `evm_mine` is not an anvil original. /// and `ganache` may change the `0x0` placeholder. - pub async fn evm_mine_detailed( - &self, - opts: Option, - ) -> Result> { + pub async fn evm_mine_detailed(&self, opts: Option) -> Result> { node_info!("evm_mine_detailed"); let mined_blocks = self.do_evm_mine(opts).await?; @@ -2196,7 +2181,7 @@ impl EthApi { BlockTransactions::Hashes(_) | BlockTransactions::Uncle => unreachable!(), }; for tx in block_txs.iter_mut() { - if let Some(receipt) = self.backend.mined_transaction_receipt(tx.hash) { + if let Some(receipt) = self.backend.mined_transaction_receipt(tx.tx_hash()) { if let Some(output) = receipt.out { // insert revert reason if failure if !receipt @@ -2359,10 +2344,10 @@ impl EthApi { /// See [here](https://geth.ethereum.org/docs/rpc/ns-txpool#txpool_content) for more details /// /// Handler for ETH RPC call: `txpool_inspect` - pub async fn txpool_content(&self) -> Result { + pub async fn txpool_content(&self) -> Result> { node_info!("txpool_content"); - let mut content = TxpoolContent::default(); - fn convert(tx: Arc) -> Transaction { + let mut content = TxpoolContent::::default(); + fn convert(tx: Arc) -> Result { let from = *tx.pending_transaction.sender(); let mut tx = transaction_build( Some(tx.hash()), @@ -2375,18 +2360,19 @@ impl EthApi { // we set the from field here explicitly to the set sender of the pending transaction, // in case the transaction is impersonated. tx.from = from; - tx.inner + + Ok(tx) } for pending in self.pool.ready_transactions() { let entry = content.pending.entry(*pending.pending_transaction.sender()).or_default(); let key = pending.pending_transaction.nonce().to_string(); - entry.insert(key, convert(pending)); + entry.insert(key, convert(pending)?); } for queued in self.pool.pending_transactions() { let entry = content.pending.entry(*queued.pending_transaction.sender()).or_default(); let key = queued.pending_transaction.nonce().to_string(); - entry.insert(key, convert(queued)); + entry.insert(key, convert(queued)?); } Ok(content) @@ -2803,14 +2789,14 @@ impl EthApi { } /// Returns the pending block with tx hashes - async fn pending_block(&self) -> AnyNetworkBlock { + async fn pending_block(&self) -> AnyRpcBlock { let transactions = self.pool.ready_transactions().collect::>(); let info = self.backend.pending_block(transactions).await; self.backend.convert_block(info.block) } /// Returns the full pending block with `Transaction` objects - async fn pending_block_full(&self) -> Option { + async fn pending_block_full(&self) -> Option { let transactions = self.pool.ready_transactions().collect::>(); let BlockInfo { block, transactions, receipts: _ } = self.backend.pending_block(transactions).await; @@ -2925,7 +2911,7 @@ impl EthApi { TypedTransactionRequest::Legacy(_) => Signature::from_scalars_and_parity( B256::with_last_byte(1), B256::with_last_byte(1), - Parity::NonEip155(false), + false, ), TypedTransactionRequest::EIP2930(_) | TypedTransactionRequest::EIP1559(_) | @@ -2933,10 +2919,9 @@ impl EthApi { TypedTransactionRequest::Deposit(_) => Signature::from_scalars_and_parity( B256::with_last_byte(1), B256::with_last_byte(1), - Parity::Parity(false), + false, ), } - .unwrap() } /// Returns the nonce of the `address` depending on the `block_number` diff --git a/crates/anvil/src/eth/backend/db.rs b/crates/anvil/src/eth/backend/db.rs index 174933c34..db34d9c19 100644 --- a/crates/anvil/src/eth/backend/db.rs +++ b/crates/anvil/src/eth/backend/db.rs @@ -569,8 +569,8 @@ mod test { let block = r#"{ "header": { "parentHash": "0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929", - "ommersHash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "beneficiary": "0x0000000000000000000000000000000000000000", + "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", + "miner": "0x0000000000000000000000000000000000000000", "stateRoot": "0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1", "transactionsRoot": "0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988", "receiptsRoot": "0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa", diff --git a/crates/anvil/src/eth/backend/fork.rs b/crates/anvil/src/eth/backend/fork.rs index 7d887f697..64852c802 100644 --- a/crates/anvil/src/eth/backend/fork.rs +++ b/crates/anvil/src/eth/backend/fork.rs @@ -3,7 +3,7 @@ use crate::eth::{backend::db::Db, error::BlockchainError, pool::transactions::PoolTransaction}; use alloy_consensus::Account; use alloy_eips::eip2930::AccessListResult; -use alloy_network::BlockResponse; +use alloy_network::{AnyRpcBlock, AnyRpcTransaction, BlockResponse, TransactionResponse}; use alloy_primitives::{ map::{FbHashMap, HashMap}, Address, Bytes, StorageValue, B256, U256, @@ -18,8 +18,8 @@ use alloy_rpc_types::{ geth::{GethDebugTracingOptions, GethTrace}, parity::LocalizedTransactionTrace as Trace, }, - AnyNetworkBlock, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, - EIP1186AccountProofResponse, FeeHistory, Filter, Log, Transaction, + BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, EIP1186AccountProofResponse, + FeeHistory, Filter, Log, }; use alloy_serde::WithOtherFields; use alloy_transport::TransportError; @@ -291,7 +291,7 @@ impl ClientFork { &self, number: u64, index: usize, - ) -> Result>, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_number(number).await? { match block.transactions() { BlockTransactions::Full(txs) => { @@ -315,7 +315,7 @@ impl ClientFork { &self, hash: B256, index: usize, - ) -> Result>, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_hash(hash).await? { match block.transactions() { BlockTransactions::Full(txs) => { @@ -338,7 +338,7 @@ impl ClientFork { pub async fn transaction_by_hash( &self, hash: B256, - ) -> Result>, TransportError> { + ) -> Result, TransportError> { trace!(target: "backend::fork", "transaction_by_hash={:?}", hash); if let tx @ Some(_) = self.storage_read().transactions.get(&hash).cloned() { return Ok(tx); @@ -450,10 +450,7 @@ impl ClientFork { Ok(None) } - pub async fn block_by_hash( - &self, - hash: B256, - ) -> Result, TransportError> { + pub async fn block_by_hash(&self, hash: B256) -> Result, TransportError> { if let Some(mut block) = self.storage_read().blocks.get(&hash).cloned() { block.transactions.convert_to_hashes(); return Ok(Some(block)); @@ -468,7 +465,7 @@ impl ClientFork { pub async fn block_by_hash_full( &self, hash: B256, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.storage_read().blocks.get(&hash).cloned() { return Ok(Some(self.convert_to_full_block(block))); } @@ -478,7 +475,7 @@ impl ClientFork { pub async fn block_by_number( &self, block_number: u64, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(mut block) = self .storage_read() .hashes @@ -499,7 +496,7 @@ impl ClientFork { pub async fn block_by_number_full( &self, block_number: u64, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self .storage_read() .hashes @@ -516,7 +513,7 @@ impl ClientFork { async fn fetch_full_block( &self, block_id: impl Into, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.provider().get_block(block_id.into(), true.into()).await? { let hash = block.header.hash; let block_number = block.header.number; @@ -526,7 +523,7 @@ impl ClientFork { BlockTransactions::Full(txs) => txs.to_owned(), _ => vec![], }; - storage.transactions.extend(block_txs.iter().map(|tx| (tx.hash, tx.clone()))); + storage.transactions.extend(block_txs.iter().map(|tx| (tx.tx_hash(), tx.clone()))); storage.hashes.insert(block_number, hash); storage.blocks.insert(hash, block.clone()); return Ok(Some(block)); @@ -539,7 +536,7 @@ impl ClientFork { &self, hash: B256, index: usize, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_hash(hash).await? { return self.uncles_by_block_and_index(block, index).await; } @@ -550,7 +547,7 @@ impl ClientFork { &self, number: u64, index: usize, - ) -> Result, TransportError> { + ) -> Result, TransportError> { if let Some(block) = self.block_by_number(number).await? { return self.uncles_by_block_and_index(block, index).await; } @@ -559,9 +556,9 @@ impl ClientFork { async fn uncles_by_block_and_index( &self, - block: AnyNetworkBlock, + block: AnyRpcBlock, index: usize, - ) -> Result, TransportError> { + ) -> Result, TransportError> { let block_hash = block.header.hash; let block_number = block.header.number; if let Some(uncles) = self.storage_read().uncles.get(&block_hash) { @@ -582,7 +579,7 @@ impl ClientFork { } /// Converts a block of hashes into a full block - fn convert_to_full_block(&self, mut block: AnyNetworkBlock) -> AnyNetworkBlock { + fn convert_to_full_block(&self, mut block: AnyRpcBlock) -> AnyRpcBlock { let storage = self.storage.read(); let block_txs_len = match block.transactions { BlockTransactions::Full(ref txs) => txs.len(), @@ -684,10 +681,10 @@ impl ClientForkConfig { /// This is used as a cache so repeated requests to the same data are not sent to the remote client #[derive(Clone, Debug, Default)] pub struct ForkedStorage { - pub uncles: FbHashMap<32, Vec>, - pub blocks: FbHashMap<32, AnyNetworkBlock>, + pub uncles: FbHashMap<32, Vec>, + pub blocks: FbHashMap<32, AnyRpcBlock>, pub hashes: HashMap, - pub transactions: FbHashMap<32, WithOtherFields>, + pub transactions: FbHashMap<32, AnyRpcTransaction>, pub transaction_receipts: FbHashMap<32, ReceiptResponse>, pub transaction_traces: FbHashMap<32, Vec>, pub logs: HashMap>, diff --git a/crates/anvil/src/eth/backend/info.rs b/crates/anvil/src/eth/backend/info.rs index 3ac359619..0f539f937 100644 --- a/crates/anvil/src/eth/backend/info.rs +++ b/crates/anvil/src/eth/backend/info.rs @@ -1,9 +1,8 @@ //! Handler that can get current storage related data use crate::mem::Backend; +use alloy_network::AnyRpcBlock; use alloy_primitives::B256; -use alloy_rpc_types::{Block as AlloyBlock, Transaction}; -use alloy_serde::WithOtherFields; use anvil_core::eth::{block::Block, transaction::TypedReceipt}; use std::{fmt, sync::Arc}; @@ -43,10 +42,7 @@ impl StorageInfo { } /// Returns the block with the given hash in the format of the ethereum API - pub fn eth_block( - &self, - hash: B256, - ) -> Option>>> { + pub fn eth_block(&self, hash: B256) -> Option { let block = self.block(hash)?; Some(self.backend.convert_block(block)) } diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index c7ff9422a..0db343358 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -34,9 +34,14 @@ use crate::{ ForkChoice, NodeConfig, PrecompileFactory, }; use alloy_chains::NamedChain; -use alloy_consensus::{Account, Header, Receipt, ReceiptWithBloom}; +use alloy_consensus::{ + Account, Header, Receipt, ReceiptWithBloom, Signed, Transaction as TransactionTrait, TxEnvelope, +}; use alloy_eips::eip4844::MAX_BLOBS_PER_BLOCK; -use alloy_network::EthereumWallet; +use alloy_network::{ + AnyHeader, AnyRpcBlock, AnyRpcTransaction, AnyTxEnvelope, AnyTxType, EthereumWallet, + UnknownTxEnvelope, UnknownTypedTransaction, +}; use alloy_primitives::{ address, hex, keccak256, utils::Unit, Address, Bytes, TxHash, TxKind, B256, U256, U64, }; @@ -53,21 +58,19 @@ use alloy_rpc_types::{ }, parity::LocalizedTransactionTrace, }, - AccessList, AnyNetworkBlock, Block as AlloyBlock, BlockId, BlockNumberOrTag as BlockNumber, - BlockTransactions, EIP1186AccountProofResponse as AccountProof, - EIP1186StorageProof as StorageProof, Filter, FilteredParams, Header as AlloyHeader, Index, Log, - Transaction, TransactionReceipt, + AccessList, Block as AlloyBlock, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, + EIP1186AccountProofResponse as AccountProof, EIP1186StorageProof as StorageProof, Filter, + FilteredParams, Header as AlloyHeader, Index, Log, Transaction, TransactionReceipt, }; -use alloy_serde::WithOtherFields; +use alloy_serde::{OtherFields, WithOtherFields}; use alloy_signer_local::PrivateKeySigner; use alloy_trie::{proof::ProofRetainer, HashBuilder, Nibbles}; use anvil_core::eth::{ block::{Block, BlockInfo}, transaction::{ - DepositReceipt, MaybeImpersonatedTransaction, PendingTransaction, ReceiptResponse, - TransactionInfo, TypedReceipt, TypedTransaction, + optimism::DepositTransaction, DepositReceipt, MaybeImpersonatedTransaction, + PendingTransaction, ReceiptResponse, TransactionInfo, TypedReceipt, TypedTransaction, }, - utils::meets_eip155, wallet::{Capabilities, DelegationCapability, WalletCapabilities}, }; use anvil_rpc::error::RpcError; @@ -89,6 +92,7 @@ use foundry_evm::{ traces::TracingInspectorConfig, }; use futures::channel::mpsc::{unbounded, UnboundedSender}; +use op_alloy_consensus::{TxDeposit, DEPOSIT_TX_TYPE_ID}; use parking_lot::{Mutex, RwLock}; use revm::{ db::WrapDatabaseRef, @@ -1709,10 +1713,7 @@ impl Backend { } } - pub async fn block_by_hash( - &self, - hash: B256, - ) -> Result, BlockchainError> { + pub async fn block_by_hash(&self, hash: B256) -> Result, BlockchainError> { trace!(target: "backend", "get block by hash {:?}", hash); if let tx @ Some(_) = self.mined_block_by_hash(hash) { return Ok(tx); @@ -1728,7 +1729,7 @@ impl Backend { pub async fn block_by_hash_full( &self, hash: B256, - ) -> Result, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "get block by hash {:?}", hash); if let tx @ Some(_) = self.get_full_block(hash) { return Ok(tx); @@ -1741,7 +1742,7 @@ impl Backend { Ok(None) } - fn mined_block_by_hash(&self, hash: B256) -> Option { + fn mined_block_by_hash(&self, hash: B256) -> Option { let block = self.blockchain.get_block_by_hash(&hash)?; Some(self.convert_block(block)) } @@ -1749,7 +1750,7 @@ impl Backend { pub(crate) async fn mined_transactions_by_block_number( &self, number: BlockNumber, - ) -> Option>> { + ) -> Option> { if let Some(block) = self.get_block(number) { return self.mined_transactions_in_block(&block); } @@ -1760,7 +1761,7 @@ impl Backend { pub(crate) fn mined_transactions_in_block( &self, block: &Block, - ) -> Option>> { + ) -> Option> { let mut transactions = Vec::with_capacity(block.transactions.len()); let base_fee = block.header.base_fee_per_gas; let storage = self.blockchain.storage.read(); @@ -1777,7 +1778,7 @@ impl Backend { pub async fn block_by_number( &self, number: BlockNumber, - ) -> Result, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "get block by number {:?}", number); if let tx @ Some(_) = self.mined_block_by_number(number) { return Ok(tx); @@ -1796,7 +1797,7 @@ impl Backend { pub async fn block_by_number_full( &self, number: BlockNumber, - ) -> Result, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "get block by number {:?}", number); if let tx @ Some(_) = self.get_full_block(number) { return Ok(tx); @@ -1849,14 +1850,14 @@ impl Backend { self.blockchain.get_block_by_hash(&hash) } - pub fn mined_block_by_number(&self, number: BlockNumber) -> Option { + pub fn mined_block_by_number(&self, number: BlockNumber) -> Option { let block = self.get_block(number)?; let mut block = self.convert_block(block); block.transactions.convert_to_hashes(); Some(block) } - pub fn get_full_block(&self, id: impl Into) -> Option { + pub fn get_full_block(&self, id: impl Into) -> Option { let block = self.get_block(id)?; let transactions = self.mined_transactions_in_block(&block)?; let mut block = self.convert_block(block); @@ -1866,63 +1867,21 @@ impl Backend { } /// Takes a block as it's stored internally and returns the eth api conform block format. - pub fn convert_block(&self, block: Block) -> AnyNetworkBlock { + pub fn convert_block(&self, block: Block) -> AnyRpcBlock { let size = U256::from(alloy_rlp::encode(&block).len() as u32); let Block { header, transactions, .. } = block; let hash = header.hash_slow(); - let Header { - parent_hash, - ommers_hash, - beneficiary, - state_root, - transactions_root, - receipts_root, - logs_bloom, - difficulty, - number, - gas_limit, - gas_used, - timestamp, - requests_hash, - extra_data, - mix_hash, - nonce, - base_fee_per_gas, - withdrawals_root, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - } = header; + let Header { number, withdrawals_root, .. } = header; let block = AlloyBlock { header: AlloyHeader { + inner: AnyHeader::from(header), hash, - parent_hash, - uncles_hash: ommers_hash, - miner: beneficiary, - state_root, - transactions_root, - receipts_root, - number, - gas_used, - gas_limit, - extra_data: extra_data.0.into(), - logs_bloom, - timestamp, total_difficulty: Some(self.total_difficulty()), - difficulty, - mix_hash: Some(mix_hash), - nonce: Some(nonce), - base_fee_per_gas, - withdrawals_root, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - requests_hash, + size: Some(size), }, - size: Some(size), transactions: alloy_rpc_types::BlockTransactions::Hashes( transactions.into_iter().map(|tx| tx.hash()).collect(), ), @@ -2030,7 +1989,7 @@ impl Backend { if let Some(state) = self.states.write().get(&block_hash) { let block = BlockEnv { number: block_number, - coinbase: block.header.miner, + coinbase: block.header.beneficiary, timestamp: U256::from(block.header.timestamp), difficulty: block.header.difficulty, prevrandao: block.header.mix_hash, @@ -2469,7 +2428,7 @@ impl Backend { &self, number: BlockNumber, index: Index, - ) -> Result>, BlockchainError> { + ) -> Result, BlockchainError> { if let Some(block) = self.mined_block_by_number(number) { return Ok(self.mined_transaction_by_block_hash_and_index(block.header.hash, index)); } @@ -2488,7 +2447,7 @@ impl Backend { &self, hash: B256, index: Index, - ) -> Result>, BlockchainError> { + ) -> Result, BlockchainError> { if let tx @ Some(_) = self.mined_transaction_by_block_hash_and_index(hash, index) { return Ok(tx); } @@ -2504,7 +2463,7 @@ impl Backend { &self, block_hash: B256, index: Index, - ) -> Option> { + ) -> Option { let (info, block, tx) = { let storage = self.blockchain.storage.read(); let block = storage.blocks.get(&block_hash).cloned()?; @@ -2526,7 +2485,7 @@ impl Backend { pub async fn transaction_by_hash( &self, hash: B256, - ) -> Result>, BlockchainError> { + ) -> Result, BlockchainError> { trace!(target: "backend", "transaction_by_hash={:?}", hash); if let tx @ Some(_) = self.mined_transaction_by_hash(hash) { return Ok(tx); @@ -2539,7 +2498,7 @@ impl Backend { Ok(None) } - pub fn mined_transaction_by_hash(&self, hash: B256) -> Option> { + pub fn mined_transaction_by_hash(&self, hash: B256) -> Option { let (info, block) = { let storage = self.blockchain.storage.read(); let MinedTransaction { info, block_hash, .. } = @@ -2604,7 +2563,7 @@ impl Backend { .map(|(key, proof)| { let storage_key: U256 = key.into(); let value = account.storage.get(&storage_key).cloned().unwrap_or_default(); - StorageProof { key: JsonStorageKey(key), value, proof } + StorageProof { key: JsonStorageKey::Hash(key), value, proof } }) .collect(), }; @@ -2749,7 +2708,7 @@ impl TransactionValidator for Backend { if let Some(legacy) = tx.as_legacy() { // if env.handler_cfg.spec_id >= SpecId::SPURIOUS_DRAGON && - !meets_eip155(chain_id.to::(), legacy.signature().v()) + legacy.tx().chain_id.is_none() { warn!(target: "backend", ?chain_id, ?tx_chain_id, "incompatible EIP155-based V"); return Err(InvalidTransactionError::IncompatibleEIP155); @@ -2880,7 +2839,7 @@ impl TransactionValidator for Backend { } } -/// Creates a `Transaction` as it's expected for the `eth` RPC api from storage data +/// Creates a `AnyRpcTransaction` as it's expected for the `eth` RPC api from storage data #[allow(clippy::too_many_arguments)] pub fn transaction_build( tx_hash: Option, @@ -2888,56 +2847,134 @@ pub fn transaction_build( block: Option<&Block>, info: Option, base_fee: Option, -) -> WithOtherFields { - let mut transaction: Transaction = eth_transaction.clone().into(); - if info.is_some() && transaction.transaction_type == Some(0x7E) { - transaction.nonce = info.as_ref().unwrap().nonce; - } +) -> AnyRpcTransaction { + if let TypedTransaction::Deposit(ref deposit_tx) = eth_transaction.transaction { + let DepositTransaction { + nonce: _, + source_hash, + from, + kind, + mint, + gas_limit, + is_system_tx, + input, + value, + } = deposit_tx.clone(); + + let dep_tx = TxDeposit { + source_hash, + input, + from, + mint: Some(mint.to()), + to: kind, + is_system_transaction: is_system_tx, + value, + gas_limit, + }; - if eth_transaction.is_dynamic_fee() { - if block.is_none() && info.is_none() { - // transaction is not mined yet, gas price is considered just `max_fee_per_gas` - transaction.gas_price = transaction.max_fee_per_gas; - } else { - // if transaction is already mined, gas price is considered base fee + priority fee: the - // effective gas price. - let base_fee = base_fee.map_or(0u128, |g| g as u128); - let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas.unwrap_or(0); - transaction.gas_price = Some(base_fee.saturating_add(max_priority_fee_per_gas)); + let ser = serde_json::to_value(&dep_tx).unwrap(); + let maybe_deposit_fields = OtherFields::try_from(ser); + + match maybe_deposit_fields { + Ok(fields) => { + let inner = UnknownTypedTransaction { + ty: AnyTxType(DEPOSIT_TX_TYPE_ID), + fields, + memo: Default::default(), + }; + + let envelope = AnyTxEnvelope::Unknown(UnknownTxEnvelope { + hash: eth_transaction.hash(), + inner, + }); + + let tx = Transaction { + inner: envelope, + block_hash: block + .as_ref() + .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))), + block_number: block.as_ref().map(|block| block.header.number), + transaction_index: info.as_ref().map(|info| info.transaction_index), + effective_gas_price: None, + from, + }; + + return WithOtherFields::new(tx); + } + Err(_) => { + error!(target: "backend", "failed to serialize deposit transaction"); + } } - } else { - transaction.max_fee_per_gas = None; - transaction.max_priority_fee_per_gas = None; } - transaction.block_hash = - block.as_ref().map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))); + let mut transaction: Transaction = eth_transaction.clone().into(); - transaction.block_number = block.as_ref().map(|block| block.header.number); + let effective_gas_price = if !eth_transaction.is_dynamic_fee() { + transaction.effective_gas_price(base_fee) + } else if block.is_none() && info.is_none() { + // transaction is not mined yet, gas price is considered just `max_fee_per_gas` + transaction.max_fee_per_gas() + } else { + // if transaction is already mined, gas price is considered base fee + priority + // fee: the effective gas price. + let base_fee = base_fee.map_or(0u128, |g| g as u128); + let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas().unwrap_or(0); - transaction.transaction_index = info.as_ref().map(|info| info.transaction_index); + base_fee.saturating_add(max_priority_fee_per_gas) + }; - // need to check if the signature of the transaction is impersonated, if so then we - // can't recover the sender, instead we use the sender from the executed transaction and set the - // impersonated hash. - if eth_transaction.is_impersonated() { - transaction.from = info.as_ref().map(|info| info.from).unwrap_or_default(); - transaction.hash = eth_transaction.impersonated_hash(transaction.from); - } else { - transaction.from = eth_transaction.recover().expect("can recover signed tx"); - } + transaction.effective_gas_price = Some(effective_gas_price); - // if a specific hash was provided we update the transaction's hash - // This is important for impersonated transactions since they all use the `BYPASS_SIGNATURE` - // which would result in different hashes - // Note: for impersonated transactions this only concerns pending transactions because there's - // no `info` yet. - if let Some(tx_hash) = tx_hash { - transaction.hash = tx_hash; - } + let envelope = transaction.inner; - transaction.to = info.as_ref().map_or(eth_transaction.to(), |status| status.to); - WithOtherFields::new(transaction) + // if a specific hash was provided we update the transaction's hash + // This is important for impersonated transactions since they all use the + // `BYPASS_SIGNATURE` which would result in different hashes + // Note: for impersonated transactions this only concerns pending transactions because + // there's // no `info` yet. + let hash = tx_hash.unwrap_or(*envelope.tx_hash()); + + let envelope = match envelope { + TxEnvelope::Legacy(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Legacy(new_signed)) + } + TxEnvelope::Eip1559(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip1559(new_signed)) + } + TxEnvelope::Eip2930(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip2930(new_signed)) + } + TxEnvelope::Eip4844(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip4844(new_signed)) + } + TxEnvelope::Eip7702(signed_tx) => { + let (t, sig, _) = signed_tx.into_parts(); + let new_signed = Signed::new_unchecked(t, sig, hash); + AnyTxEnvelope::Ethereum(TxEnvelope::Eip7702(new_signed)) + } + _ => unreachable!("unknown tx type"), + }; + + let tx = Transaction { + inner: envelope, + block_hash: block + .as_ref() + .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))), + block_number: block.as_ref().map(|block| block.header.number), + transaction_index: info.as_ref().map(|info| info.transaction_index), + from: eth_transaction.recover().expect("can recover signed tx"), + // deprecated + effective_gas_price: Some(effective_gas_price), + }; + WithOtherFields::new(tx) } /// Prove a storage key's existence or nonexistence in the account's storage trie. diff --git a/crates/anvil/src/eth/error.rs b/crates/anvil/src/eth/error.rs index 0c478ee06..394f33492 100644 --- a/crates/anvil/src/eth/error.rs +++ b/crates/anvil/src/eth/error.rs @@ -90,6 +90,8 @@ pub enum BlockchainError { EIP7702TransactionUnsupportedAtHardfork, #[error("op-stack deposit tx received but is not supported.\n\nYou can use it by running anvil with '--optimism'.")] DepositTransactionUnsupported, + #[error("UnknownTransactionType not supported ")] + UnknownTransactionType, #[error("Excess blob gas not set.")] ExcessBlobGasNotSet, #[error("{0}")] @@ -463,6 +465,9 @@ impl ToRpcResponseResult for Result { RpcError::invalid_params(err.to_string()) } err @ BlockchainError::Message(_) => RpcError::internal_error_with(err.to_string()), + err @ BlockchainError::UnknownTransactionType => { + RpcError::invalid_params(err.to_string()) + } } .into(), } diff --git a/crates/anvil/src/eth/otterscan/api.rs b/crates/anvil/src/eth/otterscan/api.rs index e73fe4dd6..617655444 100644 --- a/crates/anvil/src/eth/otterscan/api.rs +++ b/crates/anvil/src/eth/otterscan/api.rs @@ -3,7 +3,11 @@ use crate::eth::{ macros::node_info, EthApi, }; -use alloy_network::BlockResponse; +use alloy_consensus::Transaction as TransactionTrait; +use alloy_network::{ + AnyHeader, AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, AnyTxEnvelope, BlockResponse, + TransactionResponse, +}; use alloy_primitives::{Address, Bytes, B256, U256}; use alloy_rpc_types::{ trace::{ @@ -16,10 +20,8 @@ use alloy_rpc_types::{ RewardAction, TraceOutput, }, }, - AnyNetworkBlock, Block, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, - Transaction, + Block, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions, }; -use alloy_serde::WithOtherFields; use itertools::Itertools; use futures::future::join_all; @@ -90,7 +92,7 @@ impl EthApi { pub async fn erigon_get_header_by_number( &self, number: BlockNumber, - ) -> Result> { + ) -> Result> { node_info!("ots_getApiLevel"); self.backend.block_by_number(number).await @@ -146,7 +148,10 @@ impl EthApi { /// For simplicity purposes, we return the entire block instead of emptying the values that /// Otterscan doesn't want. This is the original purpose of the endpoint (to save bandwidth), /// but it doesn't seem necessary in the context of an anvil node - pub async fn ots_get_block_details(&self, number: BlockNumber) -> Result { + pub async fn ots_get_block_details( + &self, + number: BlockNumber, + ) -> Result> { node_info!("ots_getBlockDetails"); if let Some(block) = self.backend.block_by_number(number).await? { @@ -160,7 +165,10 @@ impl EthApi { /// For simplicity purposes, we return the entire block instead of emptying the values that /// Otterscan doesn't want. This is the original purpose of the endpoint (to save bandwidth), /// but it doesn't seem necessary in the context of an anvil node - pub async fn ots_get_block_details_by_hash(&self, hash: B256) -> Result { + pub async fn ots_get_block_details_by_hash( + &self, + hash: B256, + ) -> Result> { node_info!("ots_getBlockDetailsByHash"); if let Some(block) = self.backend.block_by_hash(hash).await? { @@ -178,7 +186,7 @@ impl EthApi { number: u64, page: usize, page_size: usize, - ) -> Result>> { + ) -> Result> { node_info!("ots_getBlockTransactions"); match self.backend.block_by_number_full(number.into()).await? { @@ -193,7 +201,7 @@ impl EthApi { address: Address, block_number: u64, page_size: usize, - ) -> Result { + ) -> Result>> { node_info!("ots_searchTransactionsBefore"); let best = self.backend.best_number(); @@ -236,7 +244,7 @@ impl EthApi { address: Address, block_number: u64, page_size: usize, - ) -> Result { + ) -> Result>> { node_info!("ots_searchTransactionsAfter"); let best = self.backend.best_number(); @@ -295,8 +303,8 @@ impl EthApi { for n in (from..=to).rev() { if let Some(txs) = self.backend.mined_transactions_by_block_number(n.into()).await { for tx in txs { - if U256::from(tx.nonce) == nonce && tx.from == address { - return Ok(Some(tx.hash)); + if U256::from(tx.nonce()) == nonce && tx.from == address { + return Ok(Some(tx.tx_hash())); } } } @@ -352,7 +360,10 @@ impl EthApi { /// based on the existing list. /// /// Therefore we keep it simple by keeping the data in the response - pub async fn build_ots_block_details(&self, block: AnyNetworkBlock) -> Result { + pub async fn build_ots_block_details( + &self, + block: AnyRpcBlock, + ) -> Result>> { if block.transactions.is_uncle() { return Err(BlockchainError::DataUnavailable); } @@ -375,15 +386,10 @@ impl EthApi { .iter() .fold(0, |acc, receipt| acc + receipt.gas_used * receipt.effective_gas_price); - let Block { header, uncles, transactions, size, withdrawals } = block.inner; + let Block { header, uncles, transactions, withdrawals } = block.inner; - let block = OtsSlimBlock { - header, - uncles, - transaction_count: transactions.len(), - size, - withdrawals, - }; + let block = + OtsSlimBlock { header, uncles, transaction_count: transactions.len(), withdrawals }; Ok(BlockDetails { block, @@ -399,10 +405,10 @@ impl EthApi { /// [`ots_getBlockTransactions`]: https://github.com/otterscan/otterscan/blob/develop/docs/custom-jsonrpc.md#ots_getblockdetails pub async fn build_ots_block_tx( &self, - mut block: AnyNetworkBlock, + mut block: AnyRpcBlock, page: usize, page_size: usize, - ) -> Result>> { + ) -> Result> { if block.transactions.is_uncle() { return Err(BlockchainError::DataUnavailable); } @@ -436,8 +442,7 @@ impl EthApi { let transaction_count = block.transactions().len(); let fullblock = OtsBlock { block: block.inner, transaction_count }; - let ots_block_txs = - OtsBlockTransactions::> { fullblock, receipts }; + let ots_block_txs = OtsBlockTransactions { fullblock, receipts }; Ok(ots_block_txs) } @@ -447,7 +452,7 @@ impl EthApi { hashes: Vec, first_page: bool, last_page: bool, - ) -> Result { + ) -> Result>> { let txs_futs = hashes.iter().map(|hash| async { self.transaction_by_hash(*hash).await }); let txs = join_all(txs_futs) diff --git a/crates/anvil/src/eth/pool/transactions.rs b/crates/anvil/src/eth/pool/transactions.rs index 631064549..36e421d7a 100644 --- a/crates/anvil/src/eth/pool/transactions.rs +++ b/crates/anvil/src/eth/pool/transactions.rs @@ -1,10 +1,9 @@ use crate::eth::{error::PoolError, util::hex_fmt_many}; +use alloy_network::AnyRpcTransaction; use alloy_primitives::{ map::{HashMap, HashSet}, Address, TxHash, }; -use alloy_rpc_types::Transaction as RpcTransaction; -use alloy_serde::WithOtherFields; use anvil_core::eth::transaction::{PendingTransaction, TypedTransaction}; use parking_lot::RwLock; use std::{cmp::Ordering, collections::BTreeSet, fmt, str::FromStr, sync::Arc, time::Instant}; @@ -113,10 +112,10 @@ impl fmt::Debug for PoolTransaction { } } -impl TryFrom> for PoolTransaction { +impl TryFrom for PoolTransaction { type Error = eyre::Error; - fn try_from(transaction: WithOtherFields) -> Result { - let typed_transaction = TypedTransaction::try_from(transaction)?; + fn try_from(value: AnyRpcTransaction) -> Result { + let typed_transaction = TypedTransaction::try_from(value)?; let pending_transaction = PendingTransaction::new(typed_transaction)?; Ok(Self { pending_transaction, diff --git a/crates/anvil/src/eth/sign.rs b/crates/anvil/src/eth/sign.rs index 5f99ef9ca..e2ea036a0 100644 --- a/crates/anvil/src/eth/sign.rs +++ b/crates/anvil/src/eth/sign.rs @@ -2,7 +2,7 @@ use crate::eth::error::BlockchainError; use alloy_consensus::SignableTransaction; use alloy_dyn_abi::TypedData; use alloy_network::TxSignerSync; -use alloy_primitives::{map::AddressHashMap, Address, Signature, B256, U256}; +use alloy_primitives::{map::AddressHashMap, Address, PrimitiveSignature as Signature, B256, U256}; use alloy_signer::Signer as AlloySigner; use alloy_signer_local::PrivateKeySigner; use anvil_core::eth::transaction::{ diff --git a/crates/anvil/src/tasks/mod.rs b/crates/anvil/src/tasks/mod.rs index f9ba36b60..022e7dd97 100644 --- a/crates/anvil/src/tasks/mod.rs +++ b/crates/anvil/src/tasks/mod.rs @@ -3,10 +3,10 @@ #![allow(rustdoc::private_doc_tests)] use crate::{shutdown::Shutdown, tasks::block_listener::BlockListener, EthApi}; -use alloy_network::AnyNetwork; +use alloy_network::{AnyHeader, AnyNetwork}; use alloy_primitives::B256; use alloy_provider::Provider; -use alloy_rpc_types::{anvil::Forking, AnyNetworkBlock}; +use alloy_rpc_types::anvil::Forking; use alloy_transport::Transport; use futures::StreamExt; use std::{fmt, future::Future}; @@ -129,13 +129,13 @@ impl TaskManager { P: Provider + 'static, T: Transport + Clone, { - self.spawn_block_subscription(provider, move |block| { + self.spawn_block_subscription(provider, move |header| { let api = api.clone(); async move { let _ = api .anvil_reset(Some(Forking { json_rpc_url: None, - block_number: Some(block.header.number), + block_number: Some(header.number), })) .await; } @@ -149,7 +149,7 @@ impl TaskManager { where P: Provider + 'static, T: Transport + Clone, - F: Fn(AnyNetworkBlock) -> Fut + Unpin + Send + Sync + 'static, + F: Fn(alloy_rpc_types::Header) -> Fut + Unpin + Send + Sync + 'static, Fut: Future + Send, { let shutdown = self.on_shutdown.clone(); diff --git a/crates/anvil/test-data/state-dump-legacy-stress.json b/crates/anvil/test-data/state-dump-legacy-stress.json index 50df9e039..f6605d5ad 100644 --- a/crates/anvil/test-data/state-dump-legacy-stress.json +++ b/crates/anvil/test-data/state-dump-legacy-stress.json @@ -1 +1 @@ -{"block":{"number":"0x5","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66b200cb","gas_limit":"0x1c9c380","basefee":"0x12e09c7a","difficulty":"0x0","prevrandao":"0xe7ef87fc7c2090741a6749a087e4ca8092cb4d07136008799e4ebeac3b69e34a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0x1088aa62285a00","code":"0x","storage":{}},"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd":{"nonce":1,"balance":"0x0","code":"0x6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x19ba1fac55eea44d12a01372a8eb0c2ebbf9ca21":{"nonce":1,"balance":"0x21e19df7c2963f0ac6b","code":"0x","storage":{}},"0x19c6ab860dbe2bc433574193a4409770a8748bf6":{"nonce":1,"balance":"0x21e19df8da6b7bdc410","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x40567ec443c1d1872af5155755ac3803cc3fe61e":{"nonce":1,"balance":"0x21e19da82562f921b40","code":"0x","storage":{}},"0x47d08dad17ccb558b3ea74b1a0e73a9cc804a9dc":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","storage":{"0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0x0"}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":2,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x8138ef7cf908021d117e542120b7a39065016107":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","storage":{}},"0x83a0444b93927c3afcbe46e522280390f748e171":{"nonce":1,"balance":"0x0","code":"0x6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c63430008110033","storage":{"0x5a648c35a2f5512218b4683cf10e03f5b7c9dc7346e1bf77d304ae97f60f592b":"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xc67e2bd3108604cf0168c0e5ef9cd6d78b9bb14b":{"nonce":1,"balance":"0x21e19c6edb7e2445f20","code":"0x","storage":{}},"0xeb045d78d273107348b0300c01d29b7552d622ab":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e08b86820a43ea","code":"0x","storage":{}}},"best_block_number":"0x5","blocks":[{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xcd346446ed010523161f40a5f2b512def549bfb79e165b4354488738416481f2","transactionsRoot":"0xb3a4689832e0b599260ae70362ffcf224b60571b35ff8836904a3d81e2675d66","receiptsRoot":"0x2d13fdc120ab90536fed583939de7fb68b64926a306c1f629593ca9c2c93b198","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x3ea90d","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x2e0b6260","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3ea90d","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b5061494f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xbc73db80bf4b8784ba10a8910a0b7ef85f6846d102b41dd990969ea205335354"}}],"ommers":[]},{"header":{"parentHash":"0x026ae0c6ae91f186a9befa1ac8be30eea35e30e77de51a731085221e5cd39209","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x6e4969a136061ca7a390d12830d47a151585325a8d396819fb2b958ff85e9f8f","receiptsRoot":"0xc3e81df67d3e2a6c8345a954ef250cfcc41abcc2292a5aa263071124533fc9ad","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x3c0f6","timestamp":"0x66b200ce","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x18993a68","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3c0f6","maxFeePerGas":"0x5d4285cd","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b50610380806100206000396000f3fe6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x2476e039803622aeb040f924f04c493f559aed3d6c9372ab405cb33c8c695328"}}],"ommers":[]},{"header":{"parentHash":"0x3d22100ac0ee8d5cde334f7f926191a861b0648971ebc179547df28a0224c6d0","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x9511d4711e5c30a72b0bff38a261daa75dcc5ba8b772d970a5c742244b4c861b","transactionsRoot":"0xba5fff578d3d6c2cd63acbe9bca353eaa6fe22a5c408956eff49106e0a96c507","receiptsRoot":"0xbae111f01cb07677e3a8c5031546138407c01bc964d3493d732dc4edf47d36d3","logsBloom":"0x00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000001000000000000000000000400000001000010000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x5","gasLimit":"0x1c9c380","gasUsed":"0xcae7","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x12e09c7a","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xcc4d","maxFeePerGas":"0x557e5ec4","maxPriorityFeePerGas":"0x3b9aca00","to":"0x83a0444b93927c3afcbe46e522280390f748e171","value":"0x0","accessList":[],"input":"0x3659cfe6000000000000000000000000108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xf88e7b19ee347145c257e0cf7ac4ecc2bae83ca79d7edaa231e71d3213aeb151"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x9c8eaf493f8b4edce2ba1647343eadcc0989cf461e712c0a6253ff2ca1842bb7","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xdd07c07470e1deff3749831f0f1ad8d4b6e35505e83b3c6ea14181716197cd8a","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x24a1ab52","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200c9","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xf6930be4847cac5017bbcbec2756eed19f36b4196526a98a88e311c296e3a9be","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cc","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x200d75e8","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x4","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1592fbf9","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x149d41e3b89d8324cef3feff98ef308e97bafe8745cc8461c60172bc7d4c44ba","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x0b44110186e52ff0ceb6b0776ca2992c94144a4ed712eef65ea038260ef0fcc7","receiptsRoot":"0xc2823b8eb4730d9f2657137cc2ddc2c4f22ab68e0ab826236cf6a1551ca2b3a5","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0xe61f9","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342770c0","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xe94d1","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060008061002661006d60201b61081b1760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610141565b60008060405160200161007f90610121565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b600061010b60238361009e565b9150610116826100af565b604082019050919050565b6000602082019050818103600083015261013a816100fe565b9050919050565b611000806101506000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x4feae6769d748b4f0f7c9bf21d782236c88f13906789a3ec602961296e4c3e43"}}],"ommers":[]},{"header":{"parentHash":"0xb3535af5103fd1c2bbd6dc7ff23f0799037a6542c231ebcb85abd776560fa512","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x23d74fb99ff6e42cbb5c33f92b078e37be6af2b6092459b103ff7059a6517ebc","transactionsRoot":"0x9eab45eca206fe11c107ea985c7d02fcfa442836aea3e04ba11dc4df587d5aa6","receiptsRoot":"0xe25abcfa973db8c55f73292137c626430de130a382ad4466337fefb0f7c8fde0","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x3ce3f","timestamp":"0x66b200cd","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1c0bc72b","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3d8a8","maxFeePerGas":"0x6211577c","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060405161068538038061068583398181016040528101906100329190610275565b818181600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361009b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100ae8161019d60201b61004f1760201c565b6100ef57806040517f8a8b41ec0000000000000000000000000000000000000000000000000000000081526004016100e691906102c4565b60405180910390fd5b806100fe6101b060201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050806101536101e160201b6100621760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050610414565b600080823b905060008111915050919050565b6000806040516020016101c290610362565b6040516020818303038152906040528051906020012090508091505090565b6000806040516020016101f3906103f4565b6040516020818303038152906040528051906020012090508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061024282610217565b9050919050565b61025281610237565b811461025d57600080fd5b50565b60008151905061026f81610249565b92915050565b6000806040838503121561028c5761028b610212565b5b600061029a85828601610260565b92505060206102ab85828601610260565b9150509250929050565b6102be81610237565b82525050565b60006020820190506102d960008301846102b5565b92915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b600061034c6021836102df565b9150610357826102f0565b604082019050919050565b6000602082019050818103600083015261037b8161033f565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006103de6023836102df565b91506103e982610382565b604082019050919050565b6000602082019050818103600083015261040d816103d1565b9050919050565b610262806104236000396000f3fe6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c6343000811003300000000000000000000000047d08dad17ccb558b3ea74b1a0e73a9cc804a9dc000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xb6794d5c7abed6f91d447e8efb72ef2580595a6d7c8dee57ba1dbb330970146a"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x29dd5614","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]}]} \ No newline at end of file +{"block":{"number":"0x5","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66b200cb","gas_limit":"0x1c9c380","basefee":"0x12e09c7a","difficulty":"0x0","prevrandao":"0xe7ef87fc7c2090741a6749a087e4ca8092cb4d07136008799e4ebeac3b69e34a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0x1088aa62285a00","code":"0x","storage":{}},"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd":{"nonce":1,"balance":"0x0","code":"0x6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x19ba1fac55eea44d12a01372a8eb0c2ebbf9ca21":{"nonce":1,"balance":"0x21e19df7c2963f0ac6b","code":"0x","storage":{}},"0x19c6ab860dbe2bc433574193a4409770a8748bf6":{"nonce":1,"balance":"0x21e19df8da6b7bdc410","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x40567ec443c1d1872af5155755ac3803cc3fe61e":{"nonce":1,"balance":"0x21e19da82562f921b40","code":"0x","storage":{}},"0x47d08dad17ccb558b3ea74b1a0e73a9cc804a9dc":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","storage":{"0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0x0"}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":2,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x8138ef7cf908021d117e542120b7a39065016107":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","storage":{}},"0x83a0444b93927c3afcbe46e522280390f748e171":{"nonce":1,"balance":"0x0","code":"0x6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c63430008110033","storage":{"0x5a648c35a2f5512218b4683cf10e03f5b7c9dc7346e1bf77d304ae97f60f592b":"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xc67e2bd3108604cf0168c0e5ef9cd6d78b9bb14b":{"nonce":1,"balance":"0x21e19c6edb7e2445f20","code":"0x","storage":{}},"0xeb045d78d273107348b0300c01d29b7552d622ab":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e08b86820a43ea","code":"0x","storage":{}}},"best_block_number":"0x5","blocks":[{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xcd346446ed010523161f40a5f2b512def549bfb79e165b4354488738416481f2","transactionsRoot":"0xb3a4689832e0b599260ae70362ffcf224b60571b35ff8836904a3d81e2675d66","receiptsRoot":"0x2d13fdc120ab90536fed583939de7fb68b64926a306c1f629593ca9c2c93b198","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x3ea90d","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x2e0b6260","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3ea90d","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b5061494f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xbc73db80bf4b8784ba10a8910a0b7ef85f6846d102b41dd990969ea205335354"}}],"ommers":[]},{"header":{"parentHash":"0x026ae0c6ae91f186a9befa1ac8be30eea35e30e77de51a731085221e5cd39209","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x6e4969a136061ca7a390d12830d47a151585325a8d396819fb2b958ff85e9f8f","receiptsRoot":"0xc3e81df67d3e2a6c8345a954ef250cfcc41abcc2292a5aa263071124533fc9ad","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x3c0f6","timestamp":"0x66b200ce","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x18993a68","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3c0f6","maxFeePerGas":"0x5d4285cd","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b50610380806100206000396000f3fe6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x2476e039803622aeb040f924f04c493f559aed3d6c9372ab405cb33c8c695328"}}],"ommers":[]},{"header":{"parentHash":"0x3d22100ac0ee8d5cde334f7f926191a861b0648971ebc179547df28a0224c6d0","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9511d4711e5c30a72b0bff38a261daa75dcc5ba8b772d970a5c742244b4c861b","transactionsRoot":"0xba5fff578d3d6c2cd63acbe9bca353eaa6fe22a5c408956eff49106e0a96c507","receiptsRoot":"0xbae111f01cb07677e3a8c5031546138407c01bc964d3493d732dc4edf47d36d3","logsBloom":"0x00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000001000000000000000000000400000001000010000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x5","gasLimit":"0x1c9c380","gasUsed":"0xcae7","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x12e09c7a","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xcc4d","maxFeePerGas":"0x557e5ec4","maxPriorityFeePerGas":"0x3b9aca00","to":"0x83a0444b93927c3afcbe46e522280390f748e171","value":"0x0","accessList":[],"input":"0x3659cfe6000000000000000000000000108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xf88e7b19ee347145c257e0cf7ac4ecc2bae83ca79d7edaa231e71d3213aeb151"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9c8eaf493f8b4edce2ba1647343eadcc0989cf461e712c0a6253ff2ca1842bb7","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xdd07c07470e1deff3749831f0f1ad8d4b6e35505e83b3c6ea14181716197cd8a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x24a1ab52","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200c9","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xf6930be4847cac5017bbcbec2756eed19f36b4196526a98a88e311c296e3a9be","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cc","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x200d75e8","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x4","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1592fbf9","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x149d41e3b89d8324cef3feff98ef308e97bafe8745cc8461c60172bc7d4c44ba","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x0b44110186e52ff0ceb6b0776ca2992c94144a4ed712eef65ea038260ef0fcc7","receiptsRoot":"0xc2823b8eb4730d9f2657137cc2ddc2c4f22ab68e0ab826236cf6a1551ca2b3a5","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0xe61f9","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342770c0","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xe94d1","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060008061002661006d60201b61081b1760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610141565b60008060405160200161007f90610121565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b600061010b60238361009e565b9150610116826100af565b604082019050919050565b6000602082019050818103600083015261013a816100fe565b9050919050565b611000806101506000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x4feae6769d748b4f0f7c9bf21d782236c88f13906789a3ec602961296e4c3e43"}}],"ommers":[]},{"header":{"parentHash":"0xb3535af5103fd1c2bbd6dc7ff23f0799037a6542c231ebcb85abd776560fa512","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x23d74fb99ff6e42cbb5c33f92b078e37be6af2b6092459b103ff7059a6517ebc","transactionsRoot":"0x9eab45eca206fe11c107ea985c7d02fcfa442836aea3e04ba11dc4df587d5aa6","receiptsRoot":"0xe25abcfa973db8c55f73292137c626430de130a382ad4466337fefb0f7c8fde0","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x3ce3f","timestamp":"0x66b200cd","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1c0bc72b","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3d8a8","maxFeePerGas":"0x6211577c","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060405161068538038061068583398181016040528101906100329190610275565b818181600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361009b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100ae8161019d60201b61004f1760201c565b6100ef57806040517f8a8b41ec0000000000000000000000000000000000000000000000000000000081526004016100e691906102c4565b60405180910390fd5b806100fe6101b060201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050806101536101e160201b6100621760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050610414565b600080823b905060008111915050919050565b6000806040516020016101c290610362565b6040516020818303038152906040528051906020012090508091505090565b6000806040516020016101f3906103f4565b6040516020818303038152906040528051906020012090508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061024282610217565b9050919050565b61025281610237565b811461025d57600080fd5b50565b60008151905061026f81610249565b92915050565b6000806040838503121561028c5761028b610212565b5b600061029a85828601610260565b92505060206102ab85828601610260565b9150509250929050565b6102be81610237565b82525050565b60006020820190506102d960008301846102b5565b92915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b600061034c6021836102df565b9150610357826102f0565b604082019050919050565b6000602082019050818103600083015261037b8161033f565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006103de6023836102df565b91506103e982610382565b604082019050919050565b6000602082019050818103600083015261040d816103d1565b9050919050565b610262806104236000396000f3fe6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c6343000811003300000000000000000000000047d08dad17ccb558b3ea74b1a0e73a9cc804a9dc000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xb6794d5c7abed6f91d447e8efb72ef2580595a6d7c8dee57ba1dbb330970146a"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x29dd5614","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]}]} \ No newline at end of file diff --git a/crates/anvil/test-data/state-dump-legacy.json b/crates/anvil/test-data/state-dump-legacy.json index 0641b2f7b..273442701 100644 --- a/crates/anvil/test-data/state-dump-legacy.json +++ b/crates/anvil/test-data/state-dump-legacy.json @@ -1 +1 @@ -{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdc823","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xb92480171c0235f8c6710a4047d7ee14a3be58c630839fb4422826ff3a013e44","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc823","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}}],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdc80e","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xa00dc0c9ee9a888e67ea32d8772f8cc28eff62448c9ec985ee941fcbc921ba59","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc814","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}}],"ommers":[]}]} \ No newline at end of file +{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdc823","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xb92480171c0235f8c6710a4047d7ee14a3be58c630839fb4422826ff3a013e44","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc823","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}}],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdc80e","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xa00dc0c9ee9a888e67ea32d8772f8cc28eff62448c9ec985ee941fcbc921ba59","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc814","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}}],"ommers":[]}]} \ No newline at end of file diff --git a/crates/anvil/test-data/state-dump.json b/crates/anvil/test-data/state-dump.json index 3a3c478cf..e868bf2ef 100644 --- a/crates/anvil/test-data/state-dump.json +++ b/crates/anvil/test-data/state-dump.json @@ -1 +1 @@ -{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdcc2b","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xdb639d7f8af4f0ff2aa9cc49861820e72f5f8bfeeed677d1e3569f6b1625df4a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdcc25","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x3a52101c98a4319c419681131d3585d70a6cf13a9af25136be20d451eed5480a","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc29","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}},"impersonated_sender":null}],"ommers":[]},{"header":{"parentHash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","ommersHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","beneficiary":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc2b","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}},"impersonated_sender":null}],"ommers":[]}],"transactions":[{"info":{"transaction_hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3","transaction_index":0,"from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","block_number":1},{"info":{"transaction_hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515","transaction_index":0,"from":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","address":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x1f435a603c1bf6d544a90156b572b96d7a1730028422d800839bae78bb3506d0","block_number":2}]} \ No newline at end of file +{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdcc2b","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xdb639d7f8af4f0ff2aa9cc49861820e72f5f8bfeeed677d1e3569f6b1625df4a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdcc25","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x3a52101c98a4319c419681131d3585d70a6cf13a9af25136be20d451eed5480a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc29","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}},"impersonated_sender":null}],"ommers":[]},{"header":{"parentHash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc2b","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}},"impersonated_sender":null}],"ommers":[]}],"transactions":[{"info":{"transaction_hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3","transaction_index":0,"from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","block_number":1},{"info":{"transaction_hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515","transaction_index":0,"from":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","address":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x1f435a603c1bf6d544a90156b572b96d7a1730028422d800839bae78bb3506d0","block_number":2}]} \ No newline at end of file diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index ce78d72ca..b75b088b0 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -13,7 +13,7 @@ use alloy_rpc_types::{ anvil::{ ForkedNetwork, Forking, Metadata, MineOptions, NodeEnvironment, NodeForkConfig, NodeInfo, }, - BlockId, BlockNumberOrTag, TransactionRequest, + BlockId, BlockNumberOrTag, BlockTransactionsKind, TransactionRequest, }; use alloy_serde::WithOtherFields; use anvil::{ @@ -643,7 +643,7 @@ async fn test_fork_revert_call_latest_block_timestamp() { let Multicall::getCurrentBlockCoinbaseReturn { coinbase } = multicall_contract.getCurrentBlockCoinbase().call().await.unwrap(); - assert_eq!(coinbase, latest_block.header.miner); + assert_eq!(coinbase, latest_block.header.beneficiary); } #[tokio::test(flavor = "multi_thread")] @@ -718,14 +718,16 @@ async fn test_reorg() { // The first 3 reorged blocks should have 5 transactions each for num in 14..17 { - let block = provider.get_block_by_number(num.into(), true).await.unwrap(); + let block = + provider.get_block_by_number(num.into(), BlockTransactionsKind::Full).await.unwrap(); let block = block.unwrap(); assert_eq!(block.transactions.len(), 5); } // Verify that historic blocks are still accessible for num in (0..14).rev() { - let _ = provider.get_block_by_number(num.into(), true).await.unwrap(); + let _ = + provider.get_block_by_number(num.into(), BlockTransactionsKind::Full).await.unwrap(); } // Send a few more transaction to verify the chain can still progress @@ -777,7 +779,7 @@ async fn test_reorg() { let signature = accounts[5].sign_transaction_sync(&mut tx).unwrap(); let tx = tx.into_signed(signature); let mut encoded = vec![]; - tx.tx().encode_with_signature(tx.signature(), &mut encoded, false); + tx.eip2718_encode(&mut encoded); let pre_bal = provider.get_balance(accounts[5].address()).await.unwrap(); api.anvil_reorg(ReorgOptions { diff --git a/crates/anvil/tests/it/api.rs b/crates/anvil/tests/it/api.rs index c4172b265..946118af8 100644 --- a/crates/anvil/tests/it/api.rs +++ b/crates/anvil/tests/it/api.rs @@ -266,7 +266,7 @@ async fn can_call_on_pending_block() { .call() .await .unwrap(); - assert_eq!(block.header.miner, ret_coinbase); + assert_eq!(block.header.beneficiary, ret_coinbase); } } diff --git a/crates/anvil/tests/it/eip4844.rs b/crates/anvil/tests/it/eip4844.rs index 2b965087b..ea195f000 100644 --- a/crates/anvil/tests/it/eip4844.rs +++ b/crates/anvil/tests/it/eip4844.rs @@ -1,10 +1,10 @@ use crate::utils::{http_provider, http_provider_with_signer}; -use alloy_consensus::{SidecarBuilder, SimpleCoder}; +use alloy_consensus::{SidecarBuilder, SimpleCoder, Transaction}; use alloy_eips::eip4844::{BLOB_TX_MIN_BLOB_GASPRICE, DATA_GAS_PER_BLOB, MAX_DATA_GAS_PER_BLOCK}; use alloy_network::{EthereumWallet, TransactionBuilder, TransactionBuilder4844}; use alloy_primitives::U256; use alloy_provider::Provider; -use alloy_rpc_types::{BlockId, TransactionRequest}; +use alloy_rpc_types::{BlockId, BlockTransactionsKind, TransactionRequest}; use alloy_serde::WithOtherFields; use anvil::{spawn, EthereumHardfork, NodeConfig}; @@ -176,8 +176,14 @@ async fn can_mine_blobs_when_exceeds_max_blobs() { let second_receipt = second_tx.get_receipt().await.unwrap(); let (first_block, second_block) = tokio::join!( - provider.get_block_by_number(first_receipt.block_number.unwrap().into(), false), - provider.get_block_by_number(second_receipt.block_number.unwrap().into(), false) + provider.get_block_by_number( + first_receipt.block_number.unwrap().into(), + BlockTransactionsKind::Hashes + ), + provider.get_block_by_number( + second_receipt.block_number.unwrap().into(), + BlockTransactionsKind::Hashes + ) ); assert_eq!( first_block.unwrap().unwrap().header.blob_gas_used, @@ -239,7 +245,7 @@ async fn can_correctly_estimate_blob_gas_with_recommended_fillers() { receipt.block_number.expect("Failed to get block number") ); - assert!(tx.max_fee_per_blob_gas.unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); + assert!(tx.max_fee_per_blob_gas().unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); assert_eq!(receipt.from, alice); assert_eq!(receipt.to, Some(bob)); assert_eq!( @@ -285,7 +291,7 @@ async fn can_correctly_estimate_blob_gas_with_recommended_fillers_with_signer() receipt.block_number.expect("Failed to get block number") ); - assert!(tx.max_fee_per_blob_gas.unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); + assert!(tx.max_fee_per_blob_gas().unwrap() >= BLOB_TX_MIN_BLOB_GASPRICE); assert_eq!(receipt.from, alice); assert_eq!(receipt.to, Some(bob)); assert_eq!( diff --git a/crates/anvil/tests/it/eip7702.rs b/crates/anvil/tests/it/eip7702.rs index ab787e4eb..e10633d6c 100644 --- a/crates/anvil/tests/it/eip7702.rs +++ b/crates/anvil/tests/it/eip7702.rs @@ -66,7 +66,7 @@ async fn can_send_eip7702_tx() { let tx = tx.into_signed(signature); let mut encoded = Vec::new(); - tx.tx().encode_with_signature(tx.signature(), &mut encoded, false); + tx.eip2718_encode(&mut encoded); let receipt = provider.send_raw_transaction(&encoded).await.unwrap().get_receipt().await.unwrap(); diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index 821395417..3d470894b 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -5,7 +5,7 @@ use crate::{ utils::{http_provider, http_provider_with_signer}, }; use alloy_chains::NamedChain; -use alloy_network::{EthereumWallet, ReceiptResponse, TransactionBuilder}; +use alloy_network::{EthereumWallet, ReceiptResponse, TransactionBuilder, TransactionResponse}; use alloy_primitives::{address, b256, bytes, uint, Address, Bytes, TxHash, TxKind, U256, U64}; use alloy_provider::Provider; use alloy_rpc_types::{ @@ -1407,7 +1407,7 @@ async fn test_immutable_fork_transaction_hash() { api.backend.mined_transaction_by_block_hash_and_index(hash, expected.1.into()) }) .unwrap(); - assert_eq!(tx.inner.hash.to_string(), expected.0.to_string()); + assert_eq!(tx.tx_hash().to_string(), expected.0.to_string()); } } diff --git a/crates/anvil/tests/it/ipc.rs b/crates/anvil/tests/it/ipc.rs index 4f13f8aaf..e5d99e01b 100644 --- a/crates/anvil/tests/it/ipc.rs +++ b/crates/anvil/tests/it/ipc.rs @@ -54,7 +54,7 @@ async fn test_sub_new_heads_ipc() { let blocks = provider.subscribe_blocks().await.unwrap().into_stream(); let blocks = blocks.take(3).collect::>().await; - let block_numbers = blocks.into_iter().map(|b| b.header.number).collect::>(); + let block_numbers = blocks.into_iter().map(|b| b.number).collect::>(); assert_eq!(block_numbers, vec![1, 2, 3]); } diff --git a/crates/anvil/tests/it/logs.rs b/crates/anvil/tests/it/logs.rs index 3bf09493d..ac644e6e2 100644 --- a/crates/anvil/tests/it/logs.rs +++ b/crates/anvil/tests/it/logs.rs @@ -7,7 +7,7 @@ use crate::{ use alloy_network::EthereumWallet; use alloy_primitives::{map::B256HashSet, B256}; use alloy_provider::Provider; -use alloy_rpc_types::{BlockNumberOrTag, Filter}; +use alloy_rpc_types::{BlockNumberOrTag, BlockTransactionsKind, Filter}; use anvil::{spawn, NodeConfig}; use futures::StreamExt; @@ -55,7 +55,7 @@ async fn get_past_events() { // and we can fetch the events at a block hash // let hash = provider.get_block(1).await.unwrap().unwrap().hash.unwrap(); let hash = provider - .get_block_by_number(BlockNumberOrTag::from(1), false) + .get_block_by_number(BlockNumberOrTag::from(1), BlockTransactionsKind::Hashes) .await .unwrap() .unwrap() @@ -191,7 +191,10 @@ async fn watch_events() { assert_eq!(log.1.block_number.unwrap(), starting_block_number + i + 1); let hash = provider - .get_block_by_number(BlockNumberOrTag::from(starting_block_number + i + 1), false) + .get_block_by_number( + BlockNumberOrTag::from(starting_block_number + i + 1), + false.into(), + ) .await .unwrap() .unwrap() diff --git a/crates/anvil/tests/it/otterscan.rs b/crates/anvil/tests/it/otterscan.rs index e839c9986..37d21a29e 100644 --- a/crates/anvil/tests/it/otterscan.rs +++ b/crates/anvil/tests/it/otterscan.rs @@ -1,6 +1,7 @@ //! Tests for otterscan endpoints. use crate::abi::Multicall; +use alloy_network::TransactionResponse; use alloy_primitives::{address, Address, Bytes, U256}; use alloy_provider::Provider; use alloy_rpc_types::{ @@ -409,7 +410,7 @@ async fn ots_search_transactions_before() { // check each individual hash result.txs.iter().for_each(|tx| { - assert_eq!(hashes.pop(), Some(tx.hash)); + assert_eq!(hashes.pop(), Some(tx.tx_hash())); }); block = result.txs.last().unwrap().block_number.unwrap(); @@ -444,7 +445,7 @@ async fn ots_search_transactions_after() { // check each individual hash result.txs.iter().rev().for_each(|tx| { - assert_eq!(hashes.pop_back(), Some(tx.hash)); + assert_eq!(hashes.pop_back(), Some(tx.tx_hash())); }); block = result.txs.first().unwrap().block_number.unwrap(); diff --git a/crates/anvil/tests/it/pubsub.rs b/crates/anvil/tests/it/pubsub.rs index ecfb9b100..948456055 100644 --- a/crates/anvil/tests/it/pubsub.rs +++ b/crates/anvil/tests/it/pubsub.rs @@ -23,7 +23,7 @@ async fn test_sub_new_heads() { api.anvil_set_interval_mining(1).unwrap(); let blocks = blocks.into_stream().take(3).collect::>().await; - let block_numbers = blocks.into_iter().map(|b| b.header.number).collect::>(); + let block_numbers = blocks.into_iter().map(|b| b.number).collect::>(); assert_eq!(block_numbers, vec![1, 2, 3]); } @@ -262,7 +262,7 @@ async fn test_sub_new_heads_fast() { let mut block_numbers = Vec::new(); for _ in 0..num { api.mine_one().await; - let block_number = blocks.next().await.unwrap().header.number; + let block_number = blocks.next().await.unwrap().number; block_numbers.push(block_number); } diff --git a/crates/anvil/tests/it/transaction.rs b/crates/anvil/tests/it/transaction.rs index 07c120d1c..0afce986b 100644 --- a/crates/anvil/tests/it/transaction.rs +++ b/crates/anvil/tests/it/transaction.rs @@ -2,7 +2,7 @@ use crate::{ abi::{Greeter, Multicall, SimpleStorage}, utils::{connect_pubsub, http_provider_with_signer}, }; -use alloy_network::{EthereumWallet, TransactionBuilder}; +use alloy_network::{EthereumWallet, TransactionBuilder, TransactionResponse}; use alloy_primitives::{map::B256HashSet, Address, Bytes, FixedBytes, U256}; use alloy_provider::Provider; use alloy_rpc_types::{ @@ -718,7 +718,7 @@ async fn can_get_pending_transaction() { api.mine_one().await; let mined = provider.get_transaction_by_hash(*tx.tx_hash()).await.unwrap().unwrap(); - assert_eq!(mined.hash, pending.unwrap().unwrap().hash); + assert_eq!(mined.tx_hash(), pending.unwrap().unwrap().tx_hash()); } #[tokio::test(flavor = "multi_thread")] diff --git a/crates/cast/bin/cmd/creation_code.rs b/crates/cast/bin/cmd/creation_code.rs index 04531b616..b444bff32 100644 --- a/crates/cast/bin/cmd/creation_code.rs +++ b/crates/cast/bin/cmd/creation_code.rs @@ -1,3 +1,4 @@ +use alloy_consensus::Transaction; use alloy_primitives::{Address, Bytes}; use alloy_provider::{ext::TraceApi, Provider}; use alloy_rpc_types::trace::parity::{Action, CreateAction, CreateOutput, TraceOutput}; @@ -143,9 +144,9 @@ pub async fn fetch_creation_code( let tx_data = provider.get_transaction_by_hash(creation_tx_hash).await?; let tx_data = tx_data.ok_or_eyre("Could not find creation tx data.")?; - let bytecode = if tx_data.inner.to.is_none() { + let bytecode = if tx_data.to().is_none() { // Contract was created using a standard transaction - tx_data.inner.input + tx_data.input().clone() } else { // Contract was created using a factory pattern or create2 // Extract creation code from tx traces diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 880b2fe6f..79083fa8d 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -1,3 +1,5 @@ +use alloy_consensus::Transaction; +use alloy_network::TransactionResponse; use alloy_primitives::U256; use alloy_provider::Provider; use alloy_rpc_types::BlockTransactions; @@ -115,10 +117,11 @@ impl RunArgs { .ok_or_else(|| eyre::eyre!("tx not found: {:?}", tx_hash))?; // check if the tx is a system transaction - if is_known_system_sender(tx.from) || tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) { + if is_known_system_sender(tx.from) || tx.transaction_type() == Some(SYSTEM_TRANSACTION_TYPE) + { return Err(eyre::eyre!( "{:?} is a system transaction.\nReplaying system transactions is currently not supported.", - tx.hash + tx.tx_hash() )); } @@ -140,7 +143,7 @@ impl RunArgs { if let Some(block) = &block { env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.miner; + env.block.coinbase = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); @@ -184,27 +187,28 @@ impl RunArgs { // we skip them otherwise this would cause // reverts if is_known_system_sender(tx.from) || - tx.transaction_type == Some(SYSTEM_TRANSACTION_TYPE) + tx.transaction_type() == Some(SYSTEM_TRANSACTION_TYPE) { pb.set_position((index + 1) as u64); continue; } - if tx.hash == tx_hash { + if tx.tx_hash() == tx_hash { break; } configure_tx_env(&mut env, &tx.inner); - if let Some(to) = tx.to { - trace!(tx=?tx.hash,?to, "executing previous call transaction"); + if let Some(to) = Transaction::to(tx) { + trace!(tx=?tx.tx_hash(),?to, "executing previous call transaction"); executor.transact_with_env(env.clone()).wrap_err_with(|| { format!( "Failed to execute transaction: {:?} in block {}", - tx.hash, env.block.number + tx.tx_hash(), + env.block.number ) })?; } else { - trace!(tx=?tx.hash, "executing previous create transaction"); + trace!(tx=?tx.tx_hash(), "executing previous create transaction"); if let Err(error) = executor.deploy_with_env(env.clone(), None) { match error { // Reverted transactions should be skipped @@ -213,7 +217,8 @@ impl RunArgs { return Err(error).wrap_err_with(|| { format!( "Failed to deploy transaction: {:?} in block {}", - tx.hash, env.block.number + tx.tx_hash(), + env.block.number ) }) } @@ -232,11 +237,11 @@ impl RunArgs { configure_tx_env(&mut env, &tx.inner); - if let Some(to) = tx.to { - trace!(tx=?tx.hash, to=?to, "executing call transaction"); + if let Some(to) = Transaction::to(&tx) { + trace!(tx=?tx.tx_hash(), to=?to, "executing call transaction"); TraceResult::try_from(executor.transact_with_env(env))? } else { - trace!(tx=?tx.hash, "executing create transaction"); + trace!(tx=?tx.tx_hash(), "executing create transaction"); TraceResult::try_from(executor.deploy_with_env(env, None))? } }; diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index 75272b3b1..39e821dc9 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -731,9 +731,9 @@ where .ok_or_else(|| eyre::eyre!("tx not found: {:?}", tx_hash))?; Ok(if raw { - format!("0x{}", hex::encode(TxEnvelope::try_from(tx.inner)?.encoded_2718())) + format!("0x{}", hex::encode(tx.inner.inner.encoded_2718())) } else if let Some(field) = field { - get_pretty_tx_attr(&tx, field.as_str()) + get_pretty_tx_attr(&tx.inner, field.as_str()) .ok_or_else(|| eyre::eyre!("invalid tx field: {}", field.to_string()))? } else if shell::is_json() { // to_value first to sort json object keys @@ -995,7 +995,7 @@ where Either::Right(futures::future::pending()) } => { if let (Some(block), Some(to_block)) = (block, to_block_number) { - if block.header.number > to_block { + if block.number > to_block { break; } } diff --git a/crates/cheatcodes/src/crypto.rs b/crates/cheatcodes/src/crypto.rs index cdb07720c..3fd13d9b0 100644 --- a/crates/cheatcodes/src/crypto.rs +++ b/crates/cheatcodes/src/crypto.rs @@ -15,7 +15,9 @@ use k256::{ ecdsa::SigningKey, elliptic_curve::{bigint::ArrayEncoding, sec1::ToEncodedPoint}, }; -use p256::ecdsa::{signature::hazmat::PrehashSigner, Signature, SigningKey as P256SigningKey}; +use p256::ecdsa::{ + signature::hazmat::PrehashSigner, Signature as P256Signature, SigningKey as P256SigningKey, +}; /// The BIP32 default derivation path prefix. const DEFAULT_DERIVATION_PATH_PREFIX: &str = "m/44'/60'/0'/0/"; @@ -215,23 +217,23 @@ fn create_wallet(private_key: &U256, label: Option<&str>, state: &mut Cheatcodes .abi_encode()) } -fn encode_full_sig(sig: alloy_primitives::Signature) -> Vec { +fn encode_full_sig(sig: alloy_primitives::PrimitiveSignature) -> Vec { // Retrieve v, r and s from signature. - let v = U256::from(sig.v().y_parity_byte_non_eip155().unwrap_or(sig.v().y_parity_byte())); + let v = U256::from(sig.v() as u64 + 27); let r = B256::from(sig.r()); let s = B256::from(sig.s()); (v, r, s).abi_encode() } -fn encode_compact_sig(sig: alloy_primitives::Signature) -> Vec { +fn encode_compact_sig(sig: alloy_primitives::PrimitiveSignature) -> Vec { // Implement EIP-2098 compact signature. let r = B256::from(sig.r()); let mut vs = sig.s(); - vs.set_bit(255, sig.v().y_parity()); + vs.set_bit(255, sig.v()); (r, vs).abi_encode() } -fn sign(private_key: &U256, digest: &B256) -> Result { +fn sign(private_key: &U256, digest: &B256) -> Result { // The `ecrecover` precompile does not use EIP-155. No chain ID is needed. let wallet = parse_wallet(private_key)?; let sig = wallet.sign_hash_sync(digest)?; @@ -243,7 +245,7 @@ fn sign_with_wallet( state: &mut Cheatcodes, signer: Option
, digest: &B256, -) -> Result { +) -> Result { if state.wallets().is_empty() { bail!("no wallets available"); } @@ -273,7 +275,7 @@ fn sign_with_wallet( fn sign_p256(private_key: &U256, digest: &B256) -> Result { let signing_key = parse_private_key_p256(private_key)?; - let signature: Signature = signing_key.sign_prehash(digest.as_slice())?; + let signature: P256Signature = signing_key.sign_prehash(digest.as_slice())?; let r_bytes: [u8; 32] = signature.r().to_bytes().into(); let s_bytes: [u8; 32] = signature.s().to_bytes().into(); @@ -403,7 +405,7 @@ mod tests { let result = sign_p256(&pk_u256, &digest).unwrap(); let result_bytes: [u8; 64] = result.try_into().unwrap(); - let signature = Signature::from_bytes(&result_bytes.into()).unwrap(); + let signature = P256Signature::from_bytes(&result_bytes.into()).unwrap(); let verifying_key = VerifyingKey::from(&signing_key); assert!(verifying_key.verify_prehash(digest.as_slice(), &signature).is_ok()); } diff --git a/crates/cheatcodes/src/script.rs b/crates/cheatcodes/src/script.rs index 3e1239237..b28141ae0 100644 --- a/crates/cheatcodes/src/script.rs +++ b/crates/cheatcodes/src/script.rs @@ -1,9 +1,9 @@ //! Implementations of [`Scripting`](spec::Group::Scripting) cheatcodes. use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; -use alloy_primitives::{Address, B256, U256}; +use alloy_primitives::{Address, PrimitiveSignature, B256, U256}; use alloy_rpc_types::Authorization; -use alloy_signer::{Signature, SignerSync}; +use alloy_signer::SignerSync; use alloy_signer_local::PrivateKeySigner; use alloy_sol_types::SolValue; use foundry_wallets::{multi_wallet::MultiWallet, WalletSigner}; @@ -104,9 +104,13 @@ fn write_delegation(ccx: &mut CheatsCtxt, auth: SignedAuthorization) -> Result<( Ok(()) } -fn sig_to_delegation(sig: Signature, nonce: u64, implementation: Address) -> SignedDelegation { +fn sig_to_delegation( + sig: PrimitiveSignature, + nonce: u64, + implementation: Address, +) -> SignedDelegation { SignedDelegation { - v: sig.v().y_parity() as u8, + v: sig.v() as u8, r: sig.r().into(), s: sig.s().into(), nonce, @@ -114,8 +118,8 @@ fn sig_to_delegation(sig: Signature, nonce: u64, implementation: Address) -> Sig } } -fn sig_to_auth(sig: Signature, auth: Authorization) -> SignedAuthorization { - SignedAuthorization::new_unchecked(auth, sig.v().y_parity() as u8, sig.r(), sig.s()) +fn sig_to_auth(sig: PrimitiveSignature, auth: Authorization) -> SignedAuthorization { + SignedAuthorization::new_unchecked(auth, sig.v() as u8, sig.r(), sig.s()) } impl Cheatcode for startBroadcast_0Call { diff --git a/crates/common/fmt/src/ui.rs b/crates/common/fmt/src/ui.rs index 5534e72d8..a82d2cdc3 100644 --- a/crates/common/fmt/src/ui.rs +++ b/crates/common/fmt/src/ui.rs @@ -1,11 +1,14 @@ //! Helper trait and functions to format Ethereum types. -use alloy_consensus::{AnyReceiptEnvelope, Eip658Value, Receipt, ReceiptWithBloom, TxType}; -use alloy_network::ReceiptResponse; -use alloy_primitives::{hex, Address, Bloom, Bytes, FixedBytes, Uint, B256, I256, U256, U64}; +use alloy_consensus::{ + AnyReceiptEnvelope, Eip658Value, Receipt, ReceiptWithBloom, Transaction as TxTrait, TxEnvelope, + TxType, +}; +use alloy_network::{AnyHeader, AnyRpcBlock, AnyTxEnvelope, ReceiptResponse}; +use alloy_primitives::{hex, Address, Bloom, Bytes, FixedBytes, Uint, I256, U256, U64, U8}; use alloy_rpc_types::{ - AccessListItem, AnyNetworkBlock, AnyTransactionReceipt, Block, BlockTransactions, Header, Log, - Transaction, TransactionReceipt, + AccessListItem, AnyTransactionReceipt, Block, BlockTransactions, Header, Log, Transaction, + TransactionReceipt, }; use alloy_serde::{OtherFields, WithOtherFields}; use serde::Deserialize; @@ -267,7 +270,7 @@ transactionIndex: {}", } } -impl UIfmt for Block { +impl UIfmt for Block> { fn pretty(&self) -> String { format!( " @@ -317,10 +320,210 @@ impl UIfmt for AccessListItem { } } +impl UIfmt for TxEnvelope { + fn pretty(&self) -> String { + match &self { + Self::Eip2930(tx) => format!( + " +accessList {} +chainId {} +gasLimit {} +gasPrice {} +hash {} +input {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + Self::Eip1559(tx) => format!( + " +accessList {} +chainId {} +gasLimit {} +hash {} +input {} +maxFeePerGas {} +maxPriorityFeePerGas {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + Self::Eip4844(tx) => format!( + " +accessList {} +blobVersionedHashes {} +chainId {} +gasLimit {} +hash {} +input {} +maxFeePerBlobGas {} +maxFeePerGas {} +maxPriorityFeePerGas {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.blob_versioned_hashes().unwrap_or(&[]).pretty(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.max_fee_per_blob_gas().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + Self::Eip7702(tx) => format!( + " +accessList {} +authorizationList {} +chainId {} +gasLimit {} +hash {} +input {} +maxFeePerGas {} +maxPriorityFeePerGas {} +nonce {} +r {} +s {} +to {} +type {} +value {} +yParity {}", + self.access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.authorization_list() + .as_ref() + .map(|l| serde_json::to_string(&l).unwrap()) + .unwrap_or_default(), + self.chain_id().pretty(), + self.gas_limit().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), + self.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), + ), + _ => format!( + " +gas {} +gasPrice {} +hash {} +input {} +nonce {} +r {} +s {} +to {} +type {} +v {} +value {}", + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + self.as_legacy() + .map(|tx| FixedBytes::from(tx.signature().r()).pretty()) + .unwrap_or_default(), + self.as_legacy() + .map(|tx| FixedBytes::from(tx.signature().s()).pretty()) + .unwrap_or_default(), + self.to().pretty(), + self.ty(), + self.as_legacy() + .map(|tx| (if tx.signature().v() { 1u64 } else { 0 }).pretty()) + .unwrap_or_default(), + self.value().pretty(), + ), + } + } +} + +impl UIfmt for AnyTxEnvelope { + fn pretty(&self) -> String { + match self { + Self::Ethereum(envelop) => envelop.pretty(), + Self::Unknown(tx) => { + format!( + " +hash {} +type {} +{} + ", + tx.hash.pretty(), + tx.ty(), + tx.inner.fields.pretty(), + ) + } + } + } +} impl UIfmt for Transaction { fn pretty(&self) -> String { - match self.transaction_type { - Some(1) => format!( + match &self.inner { + TxEnvelope::Eip2930(tx) => format!( " accessList {} blockHash {} @@ -339,25 +542,29 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.gas_price.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.inner.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), - Some(2) => format!( + TxEnvelope::Eip1559(tx) => format!( " accessList {} blockHash {} @@ -377,26 +584,30 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.max_fee_per_gas.pretty(), - self.max_priority_fee_per_gas.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + tx.hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), - Some(3) => format!( + TxEnvelope::Eip4844(tx) => format!( " accessList {} blobVersionedHashes {} @@ -418,28 +629,32 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), - self.blob_versioned_hashes.as_deref().unwrap_or(&[]).pretty(), + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.blob_versioned_hashes().unwrap_or(&[]).pretty(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.max_fee_per_blob_gas.pretty(), - self.max_fee_per_gas.pretty(), - self.max_priority_fee_per_gas.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + tx.hash().pretty(), + self.input().pretty(), + self.max_fee_per_blob_gas().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), - Some(4) => format!( + TxEnvelope::Eip7702(tx) => format!( " accessList {} authorizationList {} @@ -460,28 +675,32 @@ transactionIndex {} type {} value {} yParity {}", - self.access_list.as_deref().map(Vec::as_slice).unwrap_or(&[]).pretty(), - self.authorization_list + self.inner + .access_list() + .map(|a| a.iter().collect::>()) + .unwrap_or_default() + .pretty(), + self.authorization_list() .as_ref() .map(|l| serde_json::to_string(&l).unwrap()) .unwrap_or_default(), self.block_hash.pretty(), self.block_number.pretty(), - self.chain_id.pretty(), + self.chain_id().pretty(), self.from.pretty(), - self.gas.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.max_fee_per_gas.pretty(), - self.max_priority_fee_per_gas.pretty(), - self.nonce.pretty(), - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + tx.hash().pretty(), + self.input().pretty(), + self.max_fee_per_gas().pretty(), + self.max_priority_fee_per_gas().pretty(), + self.nonce().pretty(), + FixedBytes::from(tx.signature().r()).pretty(), + FixedBytes::from(tx.signature().s()).pretty(), + self.to().pretty(), self.transaction_index.pretty(), - self.transaction_type.unwrap(), - self.value.pretty(), - self.signature.map(|s| s.v).pretty(), + self.inner.ty(), + self.value().pretty(), + (if tx.signature().v() { 1u64 } else { 0 }).pretty(), ), _ => format!( " @@ -502,22 +721,52 @@ value {}", self.block_hash.pretty(), self.block_number.pretty(), self.from.pretty(), - self.gas.pretty(), - self.gas_price.pretty(), - self.hash.pretty(), - self.input.pretty(), - self.nonce, - self.signature.map(|s| s.r.to_be_bytes_vec()).pretty(), - self.signature.map(|s| s.s.to_be_bytes_vec()).pretty(), - self.to.pretty(), + self.gas_limit().pretty(), + self.gas_price().pretty(), + self.inner.tx_hash().pretty(), + self.input().pretty(), + self.nonce().pretty(), + self.inner + .as_legacy() + .map(|tx| FixedBytes::from(tx.signature().r()).pretty()) + .unwrap_or_default(), + self.inner + .as_legacy() + .map(|tx| FixedBytes::from(tx.signature().s()).pretty()) + .unwrap_or_default(), + self.to().pretty(), self.transaction_index.pretty(), - self.signature.map(|s| s.v).pretty(), - self.value.pretty(), + self.inner + .as_legacy() + .map(|tx| (if tx.signature().v() { 1u64 } else { 0 }).pretty()) + .unwrap_or_default(), + self.value().pretty(), ), } } } +impl UIfmt for Transaction { + fn pretty(&self) -> String { + format!( + " +blockHash {} +blockNumber {} +from {} +transactionIndex {} +effectiveGasPrice {} +{} + ", + self.block_hash.pretty(), + self.block_number.pretty(), + self.from.pretty(), + self.transaction_index.pretty(), + self.effective_gas_price.pretty(), + self.inner.pretty(), + ) + } +} + impl UIfmt for WithOtherFields { fn pretty(&self) -> String { format!("{}{}", self.inner.pretty(), self.other.pretty()) @@ -555,28 +804,39 @@ impl UIfmt for EthValue { } /// Returns the `UiFmt::pretty()` formatted attribute of the transactions -pub fn get_pretty_tx_attr(transaction: &Transaction, attr: &str) -> Option { +pub fn get_pretty_tx_attr(transaction: &Transaction, attr: &str) -> Option { + let sig = match &transaction.inner { + AnyTxEnvelope::Ethereum(envelope) => match &envelope { + TxEnvelope::Eip2930(tx) => Some(tx.signature()), + TxEnvelope::Eip1559(tx) => Some(tx.signature()), + TxEnvelope::Eip4844(tx) => Some(tx.signature()), + TxEnvelope::Eip7702(tx) => Some(tx.signature()), + TxEnvelope::Legacy(tx) => Some(tx.signature()), + _ => None, + }, + _ => None, + }; match attr { "blockHash" | "block_hash" => Some(transaction.block_hash.pretty()), "blockNumber" | "block_number" => Some(transaction.block_number.pretty()), "from" => Some(transaction.from.pretty()), - "gas" => Some(transaction.gas.pretty()), - "gasPrice" | "gas_price" => Some(transaction.gas_price.pretty()), - "hash" => Some(transaction.hash.pretty()), - "input" => Some(transaction.input.pretty()), - "nonce" => Some(transaction.nonce.to_string()), - "s" => transaction.signature.map(|s| B256::from(s.s).pretty()), - "r" => transaction.signature.map(|s| B256::from(s.r).pretty()), - "to" => Some(transaction.to.pretty()), + "gas" => Some(transaction.gas_limit().pretty()), + "gasPrice" | "gas_price" => Some(Transaction::gas_price(transaction).pretty()), + "hash" => Some(alloy_network::TransactionResponse::tx_hash(transaction).pretty()), + "input" => Some(transaction.input().pretty()), + "nonce" => Some(transaction.nonce().to_string()), + "s" => sig.map(|s| FixedBytes::from(s.s()).pretty()), + "r" => sig.map(|s| FixedBytes::from(s.r()).pretty()), + "to" => Some(transaction.to().pretty()), "transactionIndex" | "transaction_index" => Some(transaction.transaction_index.pretty()), - "v" => transaction.signature.map(|s| s.v.pretty()), - "value" => Some(transaction.value.pretty()), + "v" => sig.map(|s| U8::from_be_slice(&s.as_bytes()[64..]).pretty()), + "value" => Some(transaction.value().pretty()), _ => None, } } /// Returns the `UiFmt::pretty()` formatted attribute of the given block -pub fn get_pretty_block_attr(block: &AnyNetworkBlock, attr: &str) -> Option { +pub fn get_pretty_block_attr(block: &AnyRpcBlock, attr: &str) -> Option { match attr { "baseFeePerGas" | "base_fee_per_gas" => Some(block.header.base_fee_per_gas.pretty()), "difficulty" => Some(block.header.difficulty.pretty()), @@ -585,15 +845,15 @@ pub fn get_pretty_block_attr(block: &AnyNetworkBlock, attr: &str) -> Option Some(block.header.gas_used.pretty()), "hash" => Some(block.header.hash.pretty()), "logsBloom" | "logs_bloom" => Some(block.header.logs_bloom.pretty()), - "miner" | "author" => Some(block.header.miner.pretty()), + "miner" | "author" => Some(block.header.inner.beneficiary.pretty()), "mixHash" | "mix_hash" => Some(block.header.mix_hash.pretty()), "nonce" => Some(block.header.nonce.pretty()), "number" => Some(block.header.number.pretty()), "parentHash" | "parent_hash" => Some(block.header.parent_hash.pretty()), "transactionsRoot" | "transactions_root" => Some(block.header.transactions_root.pretty()), "receiptsRoot" | "receipts_root" => Some(block.header.receipts_root.pretty()), - "sha3Uncles" | "sha_3_uncles" => Some(block.header.uncles_hash.pretty()), - "size" => Some(block.size.pretty()), + "sha3Uncles" | "sha_3_uncles" => Some(block.header.ommers_hash.pretty()), + "size" => Some(block.header.size.pretty()), "stateRoot" | "state_root" => Some(block.header.state_root.pretty()), "timestamp" => Some(block.header.timestamp.pretty()), "totalDifficulty" | "total_difficult" => Some(block.header.total_difficulty.pretty()), @@ -610,37 +870,40 @@ pub fn get_pretty_block_attr(block: &AnyNetworkBlock, attr: &str) -> Option(block: &Block) -> String { +fn pretty_block_basics(block: &Block>) -> String { let Block { header: Header { hash, - parent_hash, - uncles_hash, - miner, - state_root, - transactions_root, - receipts_root, - logs_bloom, - difficulty, - number, - gas_limit, - gas_used, - timestamp, + size, total_difficulty, - extra_data, - mix_hash, - nonce, - base_fee_per_gas, - withdrawals_root, - blob_gas_used, - excess_blob_gas, - parent_beacon_block_root, - requests_hash, + inner: + AnyHeader { + parent_hash, + ommers_hash, + beneficiary, + state_root, + transactions_root, + receipts_root, + logs_bloom, + difficulty, + number, + gas_limit, + gas_used, + timestamp, + extra_data, + mix_hash, + nonce, + base_fee_per_gas, + withdrawals_root, + blob_gas_used, + excess_blob_gas, + parent_beacon_block_root, + requests_hash, + }, }, uncles: _, transactions: _, - size, withdrawals: _, } = block; format!( @@ -676,7 +939,7 @@ requestsHash {}", gas_used.pretty(), hash.pretty(), logs_bloom.pretty(), - miner.pretty(), + beneficiary.pretty(), mix_hash.pretty(), nonce.pretty(), number.pretty(), @@ -684,7 +947,7 @@ requestsHash {}", parent_beacon_block_root.pretty(), transactions_root.pretty(), receipts_root.pretty(), - uncles_hash.pretty(), + ommers_hash.pretty(), size.pretty(), state_root.pretty(), timestamp.pretty(), @@ -702,6 +965,7 @@ requestsHash {}", #[cfg(test)] mod tests { use super::*; + use alloy_primitives::B256; use similar_asserts::assert_eq; use std::str::FromStr; @@ -764,7 +1028,7 @@ r 0x6fca94073a0cf3381978662d46cf890602d3e9ccf6a31e4b69e8ecbd9 s 0x0e804161a2b56a37ca1f6f4c4b8bce926587afa0d9b1acc5165e6556c959d583 to 0x4a16A42407AA491564643E1dfc1fd50af29794eF transactionIndex 0 -v 56 +v 1 value 0 index 435 l1BlockNumber 12691036 @@ -973,7 +1237,7 @@ r 0x19f2694eb9113656dbea0b925e2e7ceb43df83e601c4116aee9c0dd99 s 0x73e5764b324a4f7679d890a198ba658ba1c8cd36983ff9797e10b1b89dbb448e to 0xdca8ce283150AB773BCbeB8d38289bdB5661dE1e transactionIndex 0 -v 37 +v 0 value 0".to_string(); let txs = match block.transactions { BlockTransactions::Full(txs) => txs, @@ -1027,11 +1291,12 @@ value 0".to_string(); #[test] fn test_pretty_tx_attr() { let block = r#"{"number":"0x3","hash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","parentHash":"0x689c70c080ca22bc0e681694fa803c1aba16a69c8b6368fed5311d279eb9de90","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x7270c1c4440180f2bd5215809ee3d545df042b67329499e1ab97eb759d31610d","stateRoot":"0x29f32984517a7d25607da485b23cefabfd443751422ca7e603395e1de9bc8a4b","receiptsRoot":"0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2","miner":"0x0000000000000000000000000000000000000000","difficulty":"0x0","totalDifficulty":"0x0","extraData":"0x","size":"0x3e8","gasLimit":"0x6691b7","gasUsed":"0x5208","timestamp":"0x5ecedbb9","transactions":[{"hash":"0xc3c5f700243de37ae986082fd2af88d2a7c2752a0c0f7b9d6ac47c729d45e067","nonce":"0x2","blockHash":"0xda53da08ef6a3cbde84c33e51c04f68c3853b6a3731f10baa2324968eee63972","blockNumber":"0x3","transactionIndex":"0x0","from":"0xfdcedc3bfca10ecb0890337fbdd1977aba84807a","to":"0xdca8ce283150ab773bcbeb8d38289bdb5661de1e","value":"0x0","gas":"0x15f90","gasPrice":"0x4a817c800","input":"0x","v":"0x25","r":"0x19f2694eb9113656dbea0b925e2e7ceb43df83e601c4116aee9c0dd99130be88","s":"0x73e5764b324a4f7679d890a198ba658ba1c8cd36983ff9797e10b1b89dbb448e"}],"uncles":[]}"#; - let block: Block = serde_json::from_str(block).unwrap(); + let block: Block> = serde_json::from_str(block).unwrap(); let txs = match block.transactions { BlockTransactions::Full(txes) => txes, _ => panic!("not full transactions"), }; + assert_eq!(None, get_pretty_tx_attr(&txs[0], "")); assert_eq!(Some("3".to_string()), get_pretty_tx_attr(&txs[0], "blockNumber")); assert_eq!( @@ -1059,7 +1324,7 @@ value 0".to_string(); get_pretty_tx_attr(&txs[0], "to") ); assert_eq!(Some("0".to_string()), get_pretty_tx_attr(&txs[0], "transactionIndex")); - assert_eq!(Some("37".to_string()), get_pretty_tx_attr(&txs[0], "v")); + assert_eq!(Some("27".to_string()), get_pretty_tx_attr(&txs[0], "v")); assert_eq!(Some("0".to_string()), get_pretty_tx_attr(&txs[0], "value")); } @@ -1096,7 +1361,7 @@ value 0".to_string(); } ); - let block: AnyNetworkBlock = serde_json::from_value(json).unwrap(); + let block: AnyRpcBlock = serde_json::from_value(json).unwrap(); assert_eq!(None, get_pretty_block_attr(&block, "")); assert_eq!(Some("7".to_string()), get_pretty_block_attr(&block, "baseFeePerGas")); diff --git a/crates/common/src/transactions.rs b/crates/common/src/transactions.rs index f0ed0b54f..b319da0d8 100644 --- a/crates/common/src/transactions.rs +++ b/crates/common/src/transactions.rs @@ -58,7 +58,7 @@ impl TransactionReceiptWithRevertReason { if let Some(block_hash) = self.receipt.block_hash { match provider - .call(&WithOtherFields::new(transaction.inner.into())) + .call(&transaction.inner.inner.into()) .block(BlockId::Hash(block_hash.into())) .await { diff --git a/crates/evm/core/Cargo.toml b/crates/evm/core/Cargo.toml index c9f5131d7..2abf9b22f 100644 --- a/crates/evm/core/Cargo.toml +++ b/crates/evm/core/Cargo.toml @@ -29,8 +29,9 @@ alloy-primitives = { workspace = true, features = [ "rlp", ] } alloy-provider.workspace = true +alloy-network.workspace = true +alloy-consensus.workspace = true alloy-rpc-types.workspace = true -alloy-serde.workspace = true alloy-sol-types.workspace = true alloy-transport.workspace = true foundry-fork-db.workspace = true diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index e70468ef9..2db34ad29 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -7,10 +7,11 @@ use crate::{ utils::{configure_tx_env, configure_tx_req_env, new_evm_with_inspector}, InspectorExt, }; +use alloy_consensus::Transaction as TransactionTrait; use alloy_genesis::GenesisAccount; +use alloy_network::{AnyRpcBlock, AnyTxEnvelope, TransactionResponse}; use alloy_primitives::{keccak256, uint, Address, TxKind, B256, U256}; -use alloy_rpc_types::{Block, BlockNumberOrTag, Transaction, TransactionRequest}; -use alloy_serde::WithOtherFields; +use alloy_rpc_types::{BlockNumberOrTag, Transaction, TransactionRequest}; use eyre::Context; use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; pub use foundry_fork_db::{cache::BlockchainDbMeta, BlockchainDb, SharedBackend}; @@ -839,7 +840,7 @@ impl Backend { &self, id: LocalForkId, transaction: B256, - ) -> eyre::Result<(u64, Block>)> { + ) -> eyre::Result<(u64, AnyRpcBlock)> { let fork = self.inner.get_fork_by_id(id)?; let tx = fork.db.db.get_transaction(transaction)?; @@ -850,14 +851,12 @@ impl Backend { // we need to subtract 1 here because we want the state before the transaction // was mined let fork_block = tx_block - 1; - Ok((fork_block, block.inner)) + Ok((fork_block, block)) } else { let block = fork.db.db.get_full_block(BlockNumberOrTag::Latest)?; let number = block.header.number; - let block = block.inner; - Ok((number, block)) } } @@ -871,7 +870,7 @@ impl Backend { env: Env, tx_hash: B256, journaled_state: &mut JournaledState, - ) -> eyre::Result> { + ) -> eyre::Result>> { trace!(?id, ?tx_hash, "replay until transaction"); let persistent_accounts = self.inner.persistent_accounts.clone(); @@ -885,17 +884,17 @@ impl Backend { // 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 == Some(SYSTEM_TRANSACTION_TYPE) + tx.transaction_type() == Some(SYSTEM_TRANSACTION_TYPE) { - trace!(tx=?tx.hash, "skipping system transaction"); + trace!(tx=?tx.tx_hash(), "skipping system transaction"); continue; } - if tx.hash == tx_hash { + if tx.tx_hash() == tx_hash { // found the target transaction return Ok(Some(tx.inner)) } - trace!(tx=?tx.hash, "committing transaction"); + trace!(tx=?tx.tx_hash(), "committing transaction"); commit_transaction( &tx.inner, @@ -1914,9 +1913,9 @@ fn is_contract_in_state(journaled_state: &JournaledState, acc: Address) -> bool } /// Updates the env's block with the block's data -fn update_env_block(env: &mut Env, block: &Block) { +fn update_env_block(env: &mut Env, block: &AnyRpcBlock) { env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.miner; + env.block.coinbase = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); @@ -1930,7 +1929,7 @@ fn update_env_block(env: &mut Env, block: &Block) { /// Executes the given transaction and commits state changes to the database _and_ the journaled /// state, with an inspector. fn commit_transaction( - tx: &Transaction, + tx: &Transaction, mut env: EnvWithHandlerCfg, journaled_state: &mut JournaledState, fork: &mut Fork, @@ -1940,7 +1939,7 @@ fn commit_transaction( ) -> eyre::Result<()> { // TODO: Remove after https://github.com/foundry-rs/foundry/pull/9131 // if the tx has the blob_versioned_hashes field, we assume it's a Cancun block - if tx.blob_versioned_hashes.is_some() { + if tx.blob_versioned_hashes().is_some() { env.handler_cfg.spec_id = SpecId::CANCUN; } diff --git a/crates/evm/core/src/fork/init.rs b/crates/evm/core/src/fork/init.rs index b32fece5a..ae3f9b7a0 100644 --- a/crates/evm/core/src/fork/init.rs +++ b/crates/evm/core/src/fork/init.rs @@ -1,10 +1,8 @@ use crate::utils::apply_chain_and_block_specific_env_changes; +use alloy_consensus::BlockHeader; use alloy_primitives::{Address, U256}; -use alloy_provider::{ - network::{BlockResponse, HeaderResponse}, - Network, Provider, -}; -use alloy_rpc_types::BlockNumberOrTag; +use alloy_provider::{network::BlockResponse, Network, Provider}; +use alloy_rpc_types::{BlockNumberOrTag, BlockTransactionsKind}; use alloy_transport::Transport; use eyre::WrapErr; use foundry_common::NON_ARCHIVE_NODE_WARNING; @@ -30,7 +28,10 @@ pub async fn environment>( let (fork_gas_price, rpc_chain_id, block) = tokio::try_join!( provider.get_gas_price(), provider.get_chain_id(), - provider.get_block_by_number(BlockNumberOrTag::Number(block_number), false) + provider.get_block_by_number( + BlockNumberOrTag::Number(block_number), + BlockTransactionsKind::Hashes + ) )?; let block = if let Some(block) = block { block @@ -66,7 +67,7 @@ pub async fn environment>( block: BlockEnv { number: U256::from(block.header().number()), timestamp: U256::from(block.header().timestamp()), - coinbase: block.header().coinbase(), + coinbase: block.header().beneficiary(), difficulty: block.header().difficulty(), prevrandao: block.header().mix_hash(), basefee: U256::from(block.header().base_fee_per_gas().unwrap_or_default()), diff --git a/crates/evm/core/src/fork/multi.rs b/crates/evm/core/src/fork/multi.rs index 14fa59aaf..112e1eeda 100644 --- a/crates/evm/core/src/fork/multi.rs +++ b/crates/evm/core/src/fork/multi.rs @@ -4,8 +4,9 @@ //! concurrently active pairs at once. use super::CreateFork; +use alloy_consensus::BlockHeader; use alloy_primitives::{map::HashMap, U256}; -use alloy_provider::network::{BlockResponse, HeaderResponse}; +use alloy_provider::network::BlockResponse; use alloy_transport::layers::RetryBackoffService; use foundry_common::provider::{ runtime_transport::RuntimeTransport, ProviderBuilder, RetryProvider, diff --git a/crates/evm/core/src/opts.rs b/crates/evm/core/src/opts.rs index 99cc8daba..9849fd1ce 100644 --- a/crates/evm/core/src/opts.rs +++ b/crates/evm/core/src/opts.rs @@ -1,8 +1,7 @@ use super::fork::environment; use crate::fork::CreateFork; use alloy_primitives::{Address, B256, U256}; -use alloy_provider::Provider; -use alloy_rpc_types::AnyNetworkBlock; +use alloy_provider::{network::AnyRpcBlock, Provider}; use eyre::WrapErr; use foundry_common::{provider::ProviderBuilder, ALCHEMY_FREE_TIER_CUPS}; use foundry_config::{Chain, Config}; @@ -87,7 +86,7 @@ impl EvmOpts { pub async fn fork_evm_env( &self, fork_url: impl AsRef, - ) -> eyre::Result<(revm::primitives::Env, AnyNetworkBlock)> { + ) -> eyre::Result<(revm::primitives::Env, AnyRpcBlock)> { let fork_url = fork_url.as_ref(); let provider = ProviderBuilder::new(fork_url) .compute_units_per_second(self.get_compute_units_per_second()) diff --git a/crates/evm/core/src/utils.rs b/crates/evm/core/src/utils.rs index d76cd087c..be9660c72 100644 --- a/crates/evm/core/src/utils.rs +++ b/crates/evm/core/src/utils.rs @@ -3,12 +3,11 @@ use crate::{ backend::DatabaseExt, constants::DEFAULT_CREATE2_DEPLOYER, precompiles::ALPHANET_P256, InspectorExt, }; +use alloy_consensus::BlockHeader; use alloy_json_abi::{Function, JsonAbi}; +use alloy_network::AnyTxEnvelope; use alloy_primitives::{Address, Selector, TxKind, U256}; -use alloy_provider::{ - network::{BlockResponse, HeaderResponse}, - Network, -}; +use alloy_provider::{network::BlockResponse, Network}; use alloy_rpc_types::{Transaction, TransactionRequest}; use foundry_config::NamedChain; use foundry_fork_db::DatabaseError; @@ -85,8 +84,10 @@ pub fn get_function<'a>( } /// Configures the env for the given RPC transaction. -pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction) { - configure_tx_req_env(env, &tx.clone().into()).expect("cannot fail"); +pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction) { + if let AnyTxEnvelope::Ethereum(tx) = &tx.inner { + configure_tx_req_env(env, &tx.clone().into()).expect("cannot fail"); + } } /// Configures the env for the given RPC transaction request. diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index cd86c4200..d3079fae7 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -8,10 +8,13 @@ use crate::{ verify::VerifierArgs, }; use alloy_primitives::{hex, Address, Bytes, U256}; -use alloy_provider::Provider; -use alloy_rpc_types::{BlockId, BlockNumberOrTag, Transaction}; +use alloy_provider::{ + network::{AnyTxEnvelope, TransactionBuilder}, + Provider, +}; +use alloy_rpc_types::{BlockId, BlockNumberOrTag, TransactionInput, TransactionRequest}; use clap::{Parser, ValueHint}; -use eyre::{OptionExt, Result}; +use eyre::{Context, OptionExt, Result}; use foundry_cli::{ opts::EtherscanOpts, utils::{self, read_constructor_args_file, LoadConfig}, @@ -19,8 +22,8 @@ use foundry_cli::{ use foundry_common::shell; use foundry_compilers::{artifacts::EvmVersion, info::ContractInfo}; use foundry_config::{figment, impl_figment_convert, Config}; -use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, utils::configure_tx_env}; -use revm_primitives::AccountInfo; +use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, utils::configure_tx_req_env}; +use revm_primitives::{AccountInfo, TxKind}; use std::path::PathBuf; impl_figment_convert!(VerifyBytecodeArgs); @@ -244,21 +247,22 @@ impl VerifyBytecodeArgs { // Setup genesis tx and env. let deployer = Address::with_last_byte(0x1); - let mut gen_tx = Transaction { - from: deployer, - to: None, - input: Bytes::from(local_bytecode_vec), - ..Default::default() - }; + let mut gen_tx_req = TransactionRequest::default() + .with_from(deployer) + .with_input(Bytes::from(local_bytecode_vec)) + .into_create(); if let Some(ref block) = genesis_block { configure_env_block(&mut env, block); - gen_tx.max_fee_per_gas = block.header.base_fee_per_gas.map(|g| g as u128); - gen_tx.gas = block.header.gas_limit; - gen_tx.gas_price = block.header.base_fee_per_gas.map(|g| g as u128); + gen_tx_req.max_fee_per_gas = block.header.base_fee_per_gas.map(|g| g as u128); + gen_tx_req.gas = Some(block.header.gas_limit); + gen_tx_req.gas_price = block.header.base_fee_per_gas.map(|g| g as u128); } - configure_tx_env(&mut env, &gen_tx); + // configure_tx_rq_env(&mut env, &gen_tx); + + configure_tx_req_env(&mut env, &gen_tx_req) + .wrap_err("Failed to configure tx request env")?; // Seed deployer account with funds let account_info = AccountInfo { @@ -268,8 +272,12 @@ impl VerifyBytecodeArgs { }; executor.backend_mut().insert_account_info(deployer, account_info); - let fork_address = - crate::utils::deploy_contract(&mut executor, &env, config.evm_spec_id(), &gen_tx)?; + let fork_address = crate::utils::deploy_contract( + &mut executor, + &env, + config.evm_spec_id(), + gen_tx_req.to, + )?; // Compare runtime bytecode let (deployed_bytecode, onchain_runtime_code) = crate::utils::get_runtime_codes( @@ -308,7 +316,7 @@ impl VerifyBytecodeArgs { let creation_data = creation_data.unwrap(); // Get transaction and receipt. trace!(creation_tx_hash = ?creation_data.transaction_hash); - let mut transaction = provider + let transaction = provider .get_transaction_by_hash(creation_data.transaction_hash) .await .or_else(|e| eyre::bail!("Couldn't fetch transaction from RPC: {:?}", e))? @@ -328,12 +336,23 @@ impl VerifyBytecodeArgs { ); }; + let mut transaction: TransactionRequest = match transaction.inner.inner { + AnyTxEnvelope::Ethereum(tx) => tx.into(), + AnyTxEnvelope::Unknown(_) => unreachable!("Unknown transaction type"), + }; + // Extract creation code from creation tx input. let maybe_creation_code = if receipt.to.is_none() && receipt.contract_address == Some(self.address) { - &transaction.input + match &transaction.input.input { + Some(input) => &input[..], + None => unreachable!("creation tx input is None"), + } } else if receipt.to == Some(DEFAULT_CREATE2_DEPLOYER) { - &transaction.input[32..] + match &transaction.input.input { + Some(input) => &input[32..], + None => unreachable!("creation tx input is None"), + } } else { eyre::bail!( "Could not extract the creation code for contract at address {}", @@ -434,35 +453,39 @@ impl VerifyBytecodeArgs { // Use `transaction.from` instead of `creation_data.contract_creator` to resolve // blockscout creation data discrepancy in case of CREATE2. - let prev_block_nonce = - provider.get_transaction_count(transaction.from).block_id(prev_block_id).await?; - transaction.nonce = prev_block_nonce; + let prev_block_nonce = provider + .get_transaction_count(transaction.from.unwrap()) + .block_id(prev_block_id) + .await?; + transaction.set_nonce(prev_block_nonce); if let Some(ref block) = block { configure_env_block(&mut env, block) } // Replace the `input` with local creation code in the creation tx. - if let Some(to) = transaction.to { + if let Some(TxKind::Call(to)) = transaction.kind() { if to == DEFAULT_CREATE2_DEPLOYER { - let mut input = transaction.input[..32].to_vec(); // Salt + let mut input = transaction.input.input.unwrap()[..32].to_vec(); // Salt input.extend_from_slice(&local_bytecode_vec); - transaction.input = Bytes::from(input); + transaction.input = TransactionInput::both(Bytes::from(input)); // Deploy default CREATE2 deployer executor.deploy_create2_deployer()?; } } else { - transaction.input = Bytes::from(local_bytecode_vec); + transaction.input = TransactionInput::both(Bytes::from(local_bytecode_vec)); } - configure_tx_env(&mut env, &transaction.inner); + // configure_req__env(&mut env, &transaction.inner); + configure_tx_req_env(&mut env, &transaction) + .wrap_err("Failed to configure tx request env")?; let fork_address = crate::utils::deploy_contract( &mut executor, &env, config.evm_spec_id(), - &transaction, + transaction.to, )?; // State committed using deploy_with_env, now get the runtime bytecode from the db. diff --git a/crates/verify/src/etherscan/mod.rs b/crates/verify/src/etherscan/mod.rs index ae1443962..ca90129d5 100644 --- a/crates/verify/src/etherscan/mod.rs +++ b/crates/verify/src/etherscan/mod.rs @@ -6,6 +6,7 @@ use crate::{ use alloy_json_abi::Function; use alloy_primitives::hex; use alloy_provider::Provider; +use alloy_rpc_types::TransactionTrait; use eyre::{eyre, Context, OptionExt, Result}; use foundry_block_explorers::{ errors::EtherscanError, @@ -402,9 +403,9 @@ impl EtherscanVerificationProvider { .ok_or_eyre("Couldn't fetch transaction receipt from RPC")?; let maybe_creation_code = if receipt.contract_address == Some(args.address) { - &transaction.input - } else if transaction.to == Some(DEFAULT_CREATE2_DEPLOYER) { - &transaction.input[32..] + transaction.inner.inner.input() + } else if transaction.to() == Some(DEFAULT_CREATE2_DEPLOYER) { + &transaction.inner.inner.input()[32..] } else { eyre::bail!("Fetching of constructor arguments is not supported for contracts created by contracts") }; diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index 19c63e7fb..a14d6af6d 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -1,8 +1,8 @@ use crate::{bytecode::VerifyBytecodeArgs, types::VerificationType}; use alloy_dyn_abi::DynSolValue; use alloy_primitives::{Address, Bytes, U256}; -use alloy_provider::Provider; -use alloy_rpc_types::{AnyNetworkBlock, BlockId, Transaction}; +use alloy_provider::{network::AnyRpcBlock, Provider}; +use alloy_rpc_types::BlockId; use clap::ValueEnum; use eyre::{OptionExt, Result}; use foundry_block_explorers::{ @@ -17,7 +17,7 @@ use reqwest::Url; use revm_primitives::{ db::Database, env::{EnvWithHandlerCfg, HandlerCfg}, - Bytecode, Env, SpecId, + Bytecode, Env, SpecId, TxKind, }; use semver::Version; use serde::{Deserialize, Serialize}; @@ -340,9 +340,9 @@ pub async fn get_tracing_executor( Ok((env, executor)) } -pub fn configure_env_block(env: &mut Env, block: &AnyNetworkBlock) { +pub fn configure_env_block(env: &mut Env, block: &AnyRpcBlock) { env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.miner; + env.block.coinbase = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); @@ -353,11 +353,12 @@ pub fn deploy_contract( executor: &mut TracingExecutor, env: &Env, spec_id: SpecId, - transaction: &Transaction, + to: Option, ) -> Result { let env_with_handler = EnvWithHandlerCfg::new(Box::new(env.clone()), HandlerCfg::new(spec_id)); - if let Some(to) = transaction.to { + if to.is_some_and(|to| to.is_call()) { + let TxKind::Call(to) = to.unwrap() else { unreachable!() }; if to != DEFAULT_CREATE2_DEPLOYER { eyre::bail!("Transaction `to` address is not the default create2 deployer i.e the tx is not a contract creation tx."); } diff --git a/crates/wallets/src/wallet_signer.rs b/crates/wallets/src/wallet_signer.rs index a7bc1a312..812df9863 100644 --- a/crates/wallets/src/wallet_signer.rs +++ b/crates/wallets/src/wallet_signer.rs @@ -2,8 +2,8 @@ use crate::error::WalletSignerError; use alloy_consensus::SignableTransaction; use alloy_dyn_abi::TypedData; use alloy_network::TxSigner; -use alloy_primitives::{hex, Address, ChainId, B256}; -use alloy_signer::{Signature, Signer}; +use alloy_primitives::{hex, Address, ChainId, PrimitiveSignature, B256}; +use alloy_signer::Signer; use alloy_signer_ledger::{HDPath as LedgerHDPath, LedgerSigner}; use alloy_signer_local::{coins_bip39::English, MnemonicBuilder, PrivateKeySigner}; use alloy_signer_trezor::{HDPath as TrezorHDPath, TrezorSigner}; @@ -198,11 +198,11 @@ macro_rules! delegate { #[async_trait] impl Signer for WalletSigner { /// Signs the given hash. - async fn sign_hash(&self, hash: &B256) -> alloy_signer::Result { + async fn sign_hash(&self, hash: &B256) -> alloy_signer::Result { delegate!(self, inner => inner.sign_hash(hash)).await } - async fn sign_message(&self, message: &[u8]) -> alloy_signer::Result { + async fn sign_message(&self, message: &[u8]) -> alloy_signer::Result { delegate!(self, inner => inner.sign_message(message)).await } @@ -222,7 +222,7 @@ impl Signer for WalletSigner { &self, payload: &T, domain: &Eip712Domain, - ) -> alloy_signer::Result + ) -> alloy_signer::Result where Self: Sized, { @@ -232,21 +232,21 @@ impl Signer for WalletSigner { async fn sign_dynamic_typed_data( &self, payload: &TypedData, - ) -> alloy_signer::Result { + ) -> alloy_signer::Result { delegate!(self, inner => inner.sign_dynamic_typed_data(payload)).await } } #[async_trait] -impl TxSigner for WalletSigner { +impl TxSigner for WalletSigner { fn address(&self) -> Address { delegate!(self, inner => alloy_signer::Signer::address(inner)) } async fn sign_transaction( &self, - tx: &mut dyn SignableTransaction, - ) -> alloy_signer::Result { + tx: &mut dyn SignableTransaction, + ) -> alloy_signer::Result { delegate!(self, inner => inner.sign_transaction(tx)).await } } From 057c8ac20d2c2580237ed24557df846b48ab35b2 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:32:32 +0530 Subject: [PATCH 56/58] feat(`anvil`): `--cache-path` (#9343) * feat(`anvil`): --cache-path * nits * test * nit * run with tempdir * nit --- Cargo.lock | 18 +++++++++++ Cargo.toml | 1 + crates/anvil/Cargo.toml | 1 + crates/anvil/src/cmd.rs | 7 ++++- crates/anvil/src/config.rs | 11 +++++++ crates/anvil/src/eth/backend/mem/cache.rs | 4 +++ crates/anvil/src/eth/backend/mem/mod.rs | 9 ++++-- crates/anvil/src/eth/backend/mem/storage.rs | 8 ++++- crates/anvil/tests/it/anvil.rs | 34 ++++++++++++++++++++- 9 files changed, 88 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebc0c4e0b..bb06adac6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,6 +262,23 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-node-bindings" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27444ea67d360508753022807cdd0b49a95c878924c9c5f8f32668b7d7768245" +dependencies = [ + "alloy-genesis", + "alloy-primitives", + "k256", + "rand", + "serde_json", + "tempfile", + "thiserror 1.0.69", + "tracing", + "url", +] + [[package]] name = "alloy-primitives" version = "0.8.12" @@ -875,6 +892,7 @@ dependencies = [ "alloy-json-abi", "alloy-json-rpc", "alloy-network", + "alloy-node-bindings", "alloy-primitives", "alloy-provider", "alloy-pubsub", diff --git a/Cargo.toml b/Cargo.toml index f5ec94b90..b2008ad5b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -203,6 +203,7 @@ alloy-transport = { version = "0.6.4", default-features = false } alloy-transport-http = { version = "0.6.4", default-features = false } alloy-transport-ipc = { version = "0.6.4", default-features = false } alloy-transport-ws = { version = "0.6.4", default-features = false } +alloy-node-bindings = { version = "0.6.4", default-features = false } ## alloy-core alloy-dyn-abi = "0.8.11" diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index b3389d2ec..39a8bc649 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -117,6 +117,7 @@ alloy-rpc-client = { workspace = true, features = ["pubsub"] } alloy-transport-ipc = { workspace = true, features = ["mock"] } alloy-provider = { workspace = true, features = ["txpool-api"] } alloy-transport-ws.workspace = true +alloy-node-bindings.workspace = true alloy-json-rpc.workspace = true alloy-pubsub.workspace = true foundry-test-utils.workspace = true diff --git a/crates/anvil/src/cmd.rs b/crates/anvil/src/cmd.rs index 839dae016..eda009418 100644 --- a/crates/anvil/src/cmd.rs +++ b/crates/anvil/src/cmd.rs @@ -189,6 +189,10 @@ pub struct NodeArgs { #[command(flatten)] pub server_config: ServerConfig, + + /// Path to the cache directory where states are stored. + #[arg(long, value_name = "PATH")] + pub cache_path: Option, } #[cfg(windows)] @@ -274,7 +278,8 @@ impl NodeArgs { .with_alphanet(self.evm_opts.alphanet) .with_disable_default_create2_deployer(self.evm_opts.disable_default_create2_deployer) .with_slots_in_an_epoch(self.slots_in_an_epoch) - .with_memory_limit(self.evm_opts.memory_limit)) + .with_memory_limit(self.evm_opts.memory_limit) + .with_cache_path(self.cache_path)) } fn account_generator(&self) -> AccountGenerator { diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index 714f91e6d..ada482329 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -189,6 +189,8 @@ pub struct NodeConfig { pub alphanet: bool, /// Do not print log messages. pub silent: bool, + /// The path where states are cached. + pub cache_path: Option, } impl NodeConfig { @@ -465,6 +467,7 @@ impl Default for NodeConfig { precompile_factory: None, alphanet: false, silent: false, + cache_path: None, } } } @@ -969,6 +972,13 @@ impl NodeConfig { self } + /// Sets the path where states are cached + #[must_use] + pub fn with_cache_path(mut self, cache_path: Option) -> Self { + self.cache_path = cache_path; + self + } + /// Configures everything related to env, backend and database and returns the /// [Backend](mem::Backend) /// @@ -1051,6 +1061,7 @@ impl NodeConfig { self.max_persisted_states, self.transaction_block_keeper, self.block_time, + self.cache_path.clone(), Arc::new(tokio::sync::RwLock::new(self.clone())), ) .await; diff --git a/crates/anvil/src/eth/backend/mem/cache.rs b/crates/anvil/src/eth/backend/mem/cache.rs index e51aaae7e..51b92c3d6 100644 --- a/crates/anvil/src/eth/backend/mem/cache.rs +++ b/crates/anvil/src/eth/backend/mem/cache.rs @@ -18,6 +18,10 @@ pub struct DiskStateCache { } impl DiskStateCache { + /// Specify the path where to create the tempdir in + pub fn with_path(self, temp_path: PathBuf) -> Self { + Self { temp_path: Some(temp_path), temp_dir: None } + } /// Returns the cache file for the given hash fn with_cache_file(&mut self, hash: B256, f: F) -> Option where diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 0db343358..83718ad82 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -103,12 +103,12 @@ use revm::{ use std::{ collections::BTreeMap, io::{Read, Write}, + path::PathBuf, sync::Arc, time::Duration, }; use storage::{Blockchain, MinedTransaction, DEFAULT_HISTORY_LIMIT}; use tokio::sync::RwLock as AsyncRwLock; - pub mod cache; pub mod fork_db; pub mod in_memory_db; @@ -227,6 +227,7 @@ impl Backend { max_persisted_states: Option, transaction_block_keeper: Option, automine_block_time: Option, + cache_path: Option, node_config: Arc>, ) -> Self { // if this is a fork then adjust the blockchain storage @@ -249,7 +250,7 @@ impl Backend { genesis.timestamp }; - let states = if prune_state_history_config.is_config_enabled() { + let mut states = if prune_state_history_config.is_config_enabled() { // if prune state history is enabled, configure the state cache only for memory prune_state_history_config .max_memory_history @@ -264,6 +265,10 @@ impl Backend { Default::default() }; + if let Some(cache_path) = cache_path { + states = states.disk_path(cache_path); + } + let (slots_in_an_epoch, precompile_factory) = { let cfg = node_config.read().await; (cfg.slots_in_an_epoch, cfg.precompile_factory.clone()) diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index d5a72fccb..056b88627 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -41,7 +41,7 @@ use foundry_evm::{ }; use parking_lot::RwLock; use revm::primitives::SpecId; -use std::{collections::VecDeque, fmt, sync::Arc, time::Duration}; +use std::{collections::VecDeque, fmt, path::PathBuf, sync::Arc, time::Duration}; // use yansi::Paint; // === various limits in number of blocks === @@ -94,6 +94,12 @@ impl InMemoryBlockStates { self } + /// Configures the path on disk where the states will cached. + pub fn disk_path(mut self, path: PathBuf) -> Self { + self.disk_cache = self.disk_cache.with_path(path); + self + } + /// This modifies the `limit` what to keep stored in memory. /// /// This will ensure the new limit adjusts based on the block time. diff --git a/crates/anvil/tests/it/anvil.rs b/crates/anvil/tests/it/anvil.rs index 65eeac70b..b5ed0c853 100644 --- a/crates/anvil/tests/it/anvil.rs +++ b/crates/anvil/tests/it/anvil.rs @@ -2,9 +2,11 @@ use alloy_consensus::EMPTY_ROOT_HASH; use alloy_eips::BlockNumberOrTag; -use alloy_primitives::Address; +use alloy_node_bindings::utils::run_with_tempdir; +use alloy_primitives::{Address, U256}; use alloy_provider::Provider; use anvil::{spawn, EthereumHardfork, NodeConfig}; +use std::time::Duration; #[tokio::test(flavor = "multi_thread")] async fn test_can_change_mining_mode() { @@ -118,3 +120,33 @@ async fn test_cancun_fields() { assert!(block.header.blob_gas_used.is_some()); assert!(block.header.excess_blob_gas.is_some()); } + +#[tokio::test(flavor = "multi_thread")] +#[cfg(not(windows))] +async fn test_cache_path() { + run_with_tempdir("custom-anvil-cache", |tmp_dir| async move { + let cache_path = tmp_dir.join("cache"); + let (api, _handle) = spawn( + NodeConfig::test() + .with_cache_path(Some(cache_path.clone())) + .with_max_persisted_states(Some(5_usize)) + .with_blocktime(Some(Duration::from_millis(1))), + ) + .await; + + api.anvil_mine(Some(U256::from(1000)), None).await.unwrap(); + + // sleep to ensure the cache is written + tokio::time::sleep(Duration::from_secs(2)).await; + + assert!(cache_path.exists()); + assert!(cache_path.read_dir().unwrap().count() > 0); + + // Clean the directory, this is to prevent an error when temp_dir is dropped. + let _ = std::fs::remove_dir_all(cache_path); + + //sleep to ensure OS file handles are released + tokio::time::sleep(Duration::from_secs(1)).await; + }) + .await; +} From 9504f78cb7bf9c4fc77de9a18f6d8383896f8238 Mon Sep 17 00:00:00 2001 From: Yash Atreya <44857776+yash-atreya@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:43:21 +0530 Subject: [PATCH 57/58] chore: rm flaky cache-path test (#9372) --- Cargo.lock | 18 ------------------ Cargo.toml | 1 - crates/anvil/Cargo.toml | 1 - crates/anvil/tests/it/anvil.rs | 34 +--------------------------------- 4 files changed, 1 insertion(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb06adac6..ebc0c4e0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -262,23 +262,6 @@ dependencies = [ "serde", ] -[[package]] -name = "alloy-node-bindings" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27444ea67d360508753022807cdd0b49a95c878924c9c5f8f32668b7d7768245" -dependencies = [ - "alloy-genesis", - "alloy-primitives", - "k256", - "rand", - "serde_json", - "tempfile", - "thiserror 1.0.69", - "tracing", - "url", -] - [[package]] name = "alloy-primitives" version = "0.8.12" @@ -892,7 +875,6 @@ dependencies = [ "alloy-json-abi", "alloy-json-rpc", "alloy-network", - "alloy-node-bindings", "alloy-primitives", "alloy-provider", "alloy-pubsub", diff --git a/Cargo.toml b/Cargo.toml index b2008ad5b..f5ec94b90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -203,7 +203,6 @@ alloy-transport = { version = "0.6.4", default-features = false } alloy-transport-http = { version = "0.6.4", default-features = false } alloy-transport-ipc = { version = "0.6.4", default-features = false } alloy-transport-ws = { version = "0.6.4", default-features = false } -alloy-node-bindings = { version = "0.6.4", default-features = false } ## alloy-core alloy-dyn-abi = "0.8.11" diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 39a8bc649..b3389d2ec 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -117,7 +117,6 @@ alloy-rpc-client = { workspace = true, features = ["pubsub"] } alloy-transport-ipc = { workspace = true, features = ["mock"] } alloy-provider = { workspace = true, features = ["txpool-api"] } alloy-transport-ws.workspace = true -alloy-node-bindings.workspace = true alloy-json-rpc.workspace = true alloy-pubsub.workspace = true foundry-test-utils.workspace = true diff --git a/crates/anvil/tests/it/anvil.rs b/crates/anvil/tests/it/anvil.rs index b5ed0c853..65eeac70b 100644 --- a/crates/anvil/tests/it/anvil.rs +++ b/crates/anvil/tests/it/anvil.rs @@ -2,11 +2,9 @@ use alloy_consensus::EMPTY_ROOT_HASH; use alloy_eips::BlockNumberOrTag; -use alloy_node_bindings::utils::run_with_tempdir; -use alloy_primitives::{Address, U256}; +use alloy_primitives::Address; use alloy_provider::Provider; use anvil::{spawn, EthereumHardfork, NodeConfig}; -use std::time::Duration; #[tokio::test(flavor = "multi_thread")] async fn test_can_change_mining_mode() { @@ -120,33 +118,3 @@ async fn test_cancun_fields() { assert!(block.header.blob_gas_used.is_some()); assert!(block.header.excess_blob_gas.is_some()); } - -#[tokio::test(flavor = "multi_thread")] -#[cfg(not(windows))] -async fn test_cache_path() { - run_with_tempdir("custom-anvil-cache", |tmp_dir| async move { - let cache_path = tmp_dir.join("cache"); - let (api, _handle) = spawn( - NodeConfig::test() - .with_cache_path(Some(cache_path.clone())) - .with_max_persisted_states(Some(5_usize)) - .with_blocktime(Some(Duration::from_millis(1))), - ) - .await; - - api.anvil_mine(Some(U256::from(1000)), None).await.unwrap(); - - // sleep to ensure the cache is written - tokio::time::sleep(Duration::from_secs(2)).await; - - assert!(cache_path.exists()); - assert!(cache_path.read_dir().unwrap().count() > 0); - - // Clean the directory, this is to prevent an error when temp_dir is dropped. - let _ = std::fs::remove_dir_all(cache_path); - - //sleep to ensure OS file handles are released - tokio::time::sleep(Duration::from_secs(1)).await; - }) - .await; -} From fef20981cbaa9c08e1ef1e3cd8bc57ccbcd1ac4e Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 21 Nov 2024 12:12:45 +0100 Subject: [PATCH 58/58] feat: add global -j, --threads (#9367) * feat: add global -j, --threads * Update crates/cli/src/opts/global.rs * fix tests after comment update --------- Co-authored-by: zerosnacks <95942363+zerosnacks@users.noreply.github.com> Co-authored-by: zerosnacks --- Cargo.lock | 1 + crates/cast/bin/cmd/create2.rs | 25 +++++++++++------- crates/cast/tests/cli/main.rs | 5 ++++ crates/cli/Cargo.toml | 3 ++- crates/cli/src/opts/global.rs | 45 ++++++++++++++++++++++---------- crates/config/README.md | 2 +- crates/forge/bin/cmd/test/mod.rs | 18 +------------ crates/forge/tests/cli/cmd.rs | 5 ++++ crates/script/src/lib.rs | 2 +- 9 files changed, 62 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebc0c4e0b..4a7cb9a73 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3686,6 +3686,7 @@ dependencies = [ "foundry-wallets", "futures", "indicatif", + "rayon", "regex", "serde", "serde_json", diff --git a/crates/cast/bin/cmd/create2.rs b/crates/cast/bin/cmd/create2.rs index 17523e094..f46066137 100644 --- a/crates/cast/bin/cmd/create2.rs +++ b/crates/cast/bin/cmd/create2.rs @@ -4,7 +4,6 @@ use eyre::{Result, WrapErr}; use rand::{rngs::StdRng, RngCore, SeedableRng}; use regex::RegexSetBuilder; use std::{ - num::NonZeroUsize, sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -73,9 +72,9 @@ pub struct Create2Args { #[arg(alias = "ch", long, value_name = "HASH", required_unless_present = "init_code")] init_code_hash: Option, - /// Number of threads to use. Defaults to and caps at the number of logical cores. - #[arg(short, long)] - jobs: Option, + /// Number of threads to use. Specifying 0 defaults to the number of logical cores. + #[arg(global = true, long, short = 'j', visible_alias = "jobs")] + threads: Option, /// Address of the caller. Used for the first 20 bytes of the salt. #[arg(long, value_name = "ADDRESS")] @@ -107,7 +106,7 @@ impl Create2Args { salt, init_code, init_code_hash, - jobs, + threads, caller, seed, no_random, @@ -168,8 +167,8 @@ impl Create2Args { let regex = RegexSetBuilder::new(regexs).case_insensitive(!case_sensitive).build()?; let mut n_threads = std::thread::available_parallelism().map_or(1, |n| n.get()); - if let Some(jobs) = jobs { - n_threads = n_threads.min(jobs.get()); + if let Some(threads) = threads { + n_threads = n_threads.min(threads); } if cfg!(test) { n_threads = n_threads.min(2); @@ -433,8 +432,14 @@ mod tests { #[test] fn j0() { - let e = - Create2Args::try_parse_from(["foundry-cli", "--starts-with=00", "-j0"]).unwrap_err(); - let _ = e.print(); + let args = Create2Args::try_parse_from([ + "foundry-cli", + "--starts-with=00", + "--init-code-hash", + &B256::ZERO.to_string(), + "-j0", + ]) + .unwrap(); + assert_eq!(args.threads, Some(0)); } } diff --git a/crates/cast/tests/cli/main.rs b/crates/cast/tests/cli/main.rs index 2483fa479..bdc4a6044 100644 --- a/crates/cast/tests/cli/main.rs +++ b/crates/cast/tests/cli/main.rs @@ -28,6 +28,11 @@ Options: -h, --help Print help (see a summary with '-h') + -j, --threads + Number of threads to use. Specifying 0 defaults to the number of logical cores + + [aliases: jobs] + -V, --version Print version diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index 9fa867db3..8b741937d 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -37,7 +37,9 @@ dotenvy = "0.15" eyre.workspace = true futures.workspace = true indicatif = "0.17" +rayon.workspace = true regex = { workspace = true, default-features = false } +serde_json.workspace = true serde.workspace = true strsim = "0.11" strum = { workspace = true, features = ["derive"] } @@ -45,7 +47,6 @@ tokio = { workspace = true, features = ["macros"] } tracing-subscriber = { workspace = true, features = ["registry", "env-filter"] } tracing.workspace = true yansi.workspace = true -serde_json.workspace = true tracing-tracy = { version = "0.11", optional = true } diff --git a/crates/cli/src/opts/global.rs b/crates/cli/src/opts/global.rs index 99690a530..ad715f241 100644 --- a/crates/cli/src/opts/global.rs +++ b/crates/cli/src/opts/global.rs @@ -3,7 +3,7 @@ use foundry_common::shell::{ColorChoice, OutputFormat, OutputMode, Shell, Verbos use serde::{Deserialize, Serialize}; /// Global options. -#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, Parser)] +#[derive(Clone, Debug, Default, Serialize, Deserialize, Parser)] pub struct GlobalOpts { /// Verbosity level of the log messages. /// @@ -16,39 +16,47 @@ pub struct GlobalOpts { /// - 3 (-vvv): Print execution traces for failing tests. /// - 4 (-vvvv): Print execution traces for all tests, and setup traces for failing tests. /// - 5 (-vvvvv): Print execution and setup traces for all tests. - #[clap(short, long, global = true, verbatim_doc_comment, conflicts_with = "quiet", action = ArgAction::Count, help_heading = "Display options")] - pub verbosity: Verbosity, + #[arg(help_heading = "Display options", global = true, short, long, verbatim_doc_comment, conflicts_with = "quiet", action = ArgAction::Count)] + verbosity: Verbosity, /// Do not print log messages. - #[clap(short, long, global = true, alias = "silent", help_heading = "Display options")] + #[arg(help_heading = "Display options", global = true, short, long, alias = "silent")] quiet: bool, /// Format log messages as JSON. - #[clap( - long, - global = true, - alias = "format-json", - conflicts_with_all = &["quiet", "color"], - help_heading = "Display options" - )] + #[arg(help_heading = "Display options", global = true, long, alias = "format-json", conflicts_with_all = &["quiet", "color"])] json: bool, /// The color of the log messages. - #[clap(long, global = true, value_enum, help_heading = "Display options")] + #[arg(help_heading = "Display options", global = true, long, value_enum)] color: Option, + + /// Number of threads to use. Specifying 0 defaults to the number of logical cores. + #[arg(global = true, long, short = 'j', visible_alias = "jobs")] + threads: Option, } impl GlobalOpts { /// Initialize the global options. - pub fn init(self) -> eyre::Result<()> { + pub fn init(&self) -> eyre::Result<()> { // Set the global shell. self.shell().set(); + // Initialize the thread pool only if `threads` was requested to avoid unnecessary overhead. + if self.threads.is_some() { + self.force_init_thread_pool()?; + } + Ok(()) } + /// Initialize the global thread pool. + pub fn force_init_thread_pool(&self) -> eyre::Result<()> { + init_thread_pool(self.threads.unwrap_or(0)) + } + /// Create a new shell instance. - pub fn shell(self) -> Shell { + pub fn shell(&self) -> Shell { let mode = match self.quiet { true => OutputMode::Quiet, false => OutputMode::Normal, @@ -62,3 +70,12 @@ impl GlobalOpts { Shell::new_with(format, mode, color, self.verbosity) } } + +/// Initialize the global thread pool. +pub fn init_thread_pool(threads: usize) -> eyre::Result<()> { + rayon::ThreadPoolBuilder::new() + .thread_name(|i| format!("foundry-{i}")) + .num_threads(threads) + .build_global()?; + Ok(()) +} diff --git a/crates/config/README.md b/crates/config/README.md index 139c2a9f5..9fcd30ac9 100644 --- a/crates/config/README.md +++ b/crates/config/README.md @@ -115,7 +115,7 @@ no_match_contract = "Bar" match_path = "*/Foo*" no_match_path = "*/Bar*" no_match_coverage = "Baz" -# Number of threads to use. Not set or zero specifies the number of logical cores. +# Number of threads to use. Specifying 0 defaults to the number of logical cores. threads = 0 # whether to show test execution progress show_progress = true diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 435c34275..59434d5eb 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -65,7 +65,7 @@ foundry_config::merge_impl_figment_convert!(TestArgs, opts, evm_opts); #[derive(Clone, Debug, Parser)] #[command(next_help_heading = "Test options")] pub struct TestArgs { - /// Include the global options. + // Include global options for users of this struct. #[command(flatten)] pub global: GlobalOpts, @@ -149,11 +149,6 @@ pub struct TestArgs { #[arg(long)] pub fuzz_input_file: Option, - /// Max concurrent threads to use. - /// Default value is the number of available CPUs. - #[arg(long, short = 'j', visible_alias = "jobs")] - pub threads: Option, - /// Show test execution progress. #[arg(long)] pub show_progress: bool, @@ -276,13 +271,6 @@ impl TestArgs { // Merge all configs. let (mut config, mut evm_opts) = self.load_config_and_evm_opts_emit_warnings()?; - // Set number of max threads to execute tests. - // If not specified then the number of threads determined by rayon will be used. - if let Some(test_threads) = config.threads { - trace!(target: "forge::test", "execute tests with {} max threads", test_threads); - rayon::ThreadPoolBuilder::new().num_threads(test_threads).build_global()?; - } - // Explicitly enable isolation for gas reports for more correct gas accounting. if self.gas_report { evm_opts.isolate = true; @@ -898,10 +886,6 @@ impl Provider for TestArgs { dict.insert("show_progress".to_string(), true.into()); } - if let Some(threads) = self.threads { - dict.insert("threads".to_string(), threads.into()); - } - Ok(Map::from([(Config::selected_profile(), dict)])) } } diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 3cd4ae5ed..e0000e01b 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -33,6 +33,11 @@ Options: -h, --help Print help (see a summary with '-h') + -j, --threads + Number of threads to use. Specifying 0 defaults to the number of logical cores + + [aliases: jobs] + -V, --version Print version diff --git a/crates/script/src/lib.rs b/crates/script/src/lib.rs index 0f0283b9f..aeea4940a 100644 --- a/crates/script/src/lib.rs +++ b/crates/script/src/lib.rs @@ -78,7 +78,7 @@ foundry_config::merge_impl_figment_convert!(ScriptArgs, opts, evm_opts); /// CLI arguments for `forge script`. #[derive(Clone, Debug, Default, Parser)] pub struct ScriptArgs { - /// Include the global options. + // Include global options for users of this struct. #[command(flatten)] pub global: GlobalOpts,