From 70827aecd395bbe54d093cdb3e9c957e79a9201e Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Mon, 19 May 2025 15:16:50 +0200 Subject: [PATCH 01/21] wip: eip712 cheacode --- crates/cheatcodes/assets/cheatcodes.json | 20 +++++++++ crates/cheatcodes/spec/src/vm.rs | 4 ++ crates/cheatcodes/src/utils.rs | 54 +++++++++++++++++++++- crates/forge/tests/cli/eip712.rs | 57 +++++++++++++++++------- testdata/cheats/Vm.sol | 1 + 5 files changed, 120 insertions(+), 16 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index eb541e269a888..4d5d35ab05953 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -4294,6 +4294,26 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "eip712HashType", + "description": "Randomly shuffles an array.", + "declaration": "function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash);", + "visibility": "external", + "mutability": "pure", + "signature": "eip712HashType(string)", + "selector": "0x6792e9e2", + "selectorBytes": [ + 103, + 146, + 233, + 226 + ] + }, + "group": "utilities", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "ensNamehash", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index a75217eaa4742..3e1aa2dba1b26 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -2889,6 +2889,10 @@ interface Vm { /// catch (bytes memory interceptedInitcode) { initcode = interceptedInitcode; } #[cheatcode(group = Utilities, safety = Unsafe)] function interceptInitcode() external; + + /// Randomly shuffles an array. + #[cheatcode(group = Utilities)] + function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash); } } diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 4735ffaa41087..229d85629d0f1 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -4,7 +4,8 @@ use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::* use alloy_dyn_abi::{DynSolType, DynSolValue}; use alloy_primitives::{aliases::B32, map::HashMap, B64, U256}; use alloy_sol_types::SolValue; -use foundry_common::ens::namehash; +use foundry_common::{ens::namehash, fs}; +use foundry_config::fs_permissions::FsAccessKind; use foundry_evm_core::constants::DEFAULT_CREATE2_DEPLOYER; use proptest::prelude::Strategy; use rand::{seq::SliceRandom, Rng, RngCore}; @@ -313,3 +314,54 @@ fn random_int(state: &mut Cheatcodes, bits: Option) -> Result { .current() .abi_encode()) } + +// `string contant schema_Foo = "Foo(bar uin256)";` +const TYPE_BINDING_PREFIX: &str = "string constant schema_"; + +impl Cheatcode for eip712HashTypeCall { + fn apply(&self, state: &mut Cheatcodes) -> Result { + let Self { typeDefinition } = self; + + let type_def = if typeDefinition.contains('(') { + &get_type_def_from_bindings(typeDefinition, state)? + } else { + typeDefinition + }; + + todo!() + } +} + +fn get_type_def_from_bindings(name: &String, state: &mut Cheatcodes) -> Result { + let path = state.config.ensure_path_allowed( + &state.config.root.join("utils").join("JsonBindings.sol"), + FsAccessKind::Read, + )?; + + let content = fs::read_to_string(path)?; + + let mut type_defs = HashMap::new(); + for line in content.lines() { + let line = line.trim(); + if !line.starts_with(TYPE_BINDING_PREFIX) { + continue; + } + + let relevant = &line[TYPE_BINDING_PREFIX.len()..]; + if let Some(idx) = relevant.find('=') { + let name = relevant[..idx].trim(); + + // relevant value chars are " \"Foo(bar uint256)\";" + let def = relevant[idx + 1..].trim(); + if def.len() > 3 && def.starts_with('"') && def.ends_with("\";") { + let value = &def[1..def.len() - 2]; + type_defs.insert(name, value); + } + } + } + + match type_defs.get(name.as_str()) { + Some(value) => Ok(value.to_string()), + None => bail!(format!("'{name}' not found in 'utils/JsonBindings.sol'\n{:#?}", type_defs)), + } +} diff --git a/crates/forge/tests/cli/eip712.rs b/crates/forge/tests/cli/eip712.rs index 62aa63079eb4e..8708c034caf96 100644 --- a/crates/forge/tests/cli/eip712.rs +++ b/crates/forge/tests/cli/eip712.rs @@ -1,27 +1,21 @@ -forgetest!(test_eip712, |prj, cmd| { - let path = prj - .add_source( - "Structs", - r#" +use foundry_config::fs_permissions::PathPermission; + +const STRUCTS: &str = r#" library Structs { struct Foo { Bar bar; } - struct Bar { Art art; } - struct Art { uint256 id; } - struct Complex { Structs2.Foo foo2; Foo[] foos; Rec[][] recs; } - struct Rec { Rec[] rec; } @@ -31,15 +25,12 @@ library Structs2 { struct Foo { uint256 id; } - struct Rec { Bar[] bar; } - struct Bar { Rec rec; } - struct FooBar { Foo[] foos; Bar[] bars; @@ -49,9 +40,10 @@ library Structs2 { Structs.Rec rec; } } -"#, - ) - .unwrap(); +"#; + +forgetest!(test_eip712, |prj, cmd| { + let path = prj.add_source("Structs", STRUCTS).unwrap(); cmd.forge_fuse().args(["eip712", path.to_string_lossy().as_ref()]).assert_success().stdout_eq( str![[r#" @@ -77,3 +69,38 @@ FooBar(Foo[] foos,Bar[] bars,Foo_1 foo,Bar_1 bar,Rec[] recs,Rec_1 rec)Art(uint25 "#]], ); }); + +forgetest!(test_eip712_cheacode, |prj, cmd| { + prj.add_source("Structs", STRUCTS).unwrap(); + prj.insert_ds_test(); + prj.insert_vm(); + + prj.add_source( + "Eip712Cheat.sol", + r#" +// Note Used in forge-cli tests to assert failures. +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.18; + +import "./test.sol"; +import "./Vm.sol"; + +contract Eip712Test is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testReadUtils() public pure { + vm.eip712HashType("Foo_0"); + } +} +"#, + ) + .unwrap(); + + cmd.forge_fuse().args(["bind-json"]).assert_success(); + + let bindings = prj.root().join("utils").join("JsonBindings.sol"); + assert!(bindings.exists(), "JsonBindings.sol was not generated at {:?}", bindings); + + prj.update_config(|config| config.fs_permissions.add(PathPermission::read(bindings))); + cmd.forge_fuse().args(["test", "--mc", "Eip712Test", "-vvvv"]).assert_success(); +}); diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 6d054abbfc6ec..538ff290733f8 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -208,6 +208,7 @@ interface Vm { function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) external pure returns (uint256 privateKey); function difficulty(uint256 newDifficulty) external; function dumpState(string calldata pathToStateJson) external; + function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash); function ensNamehash(string calldata name) external pure returns (bytes32); function envAddress(string calldata name) external view returns (address value); function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); From ef3c1b968b3cb5740d9f1d7fa3c517cd779b5a94 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Tue, 20 May 2025 08:44:39 -0500 Subject: [PATCH 02/21] wip: integrate json-bind --- crates/cheatcodes/src/utils.rs | 12 +++-- crates/forge/tests/cli/eip712.rs | 85 +++++++++++++++++++------------- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 229d85629d0f1..fc11095f2e6db 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -1,8 +1,8 @@ //! Implementations of [`Utilities`](spec::Group::Utilities) cheatcodes. use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; -use alloy_dyn_abi::{DynSolType, DynSolValue}; -use alloy_primitives::{aliases::B32, map::HashMap, B64, U256}; +use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue, Resolver}; +use alloy_primitives::{aliases::B32, keccak256, map::HashMap, B64, U256}; use alloy_sol_types::SolValue; use foundry_common::{ens::namehash, fs}; use foundry_config::fs_permissions::FsAccessKind; @@ -322,13 +322,17 @@ impl Cheatcode for eip712HashTypeCall { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self { typeDefinition } = self; - let type_def = if typeDefinition.contains('(') { + let type_def = if !typeDefinition.contains('(') { &get_type_def_from_bindings(typeDefinition, state)? } else { typeDefinition + // let canonical = EncodeType::parse(typeDefinition).and_then(|parsed| + // parsed.canonicalize())?; }; - todo!() + // let hash = keccak256(type_def.as_bytes()); + // bail!("type: {type_def}, hash: {hash}"); + Ok(keccak256(type_def.as_bytes()).to_vec()) } } diff --git a/crates/forge/tests/cli/eip712.rs b/crates/forge/tests/cli/eip712.rs index 8708c034caf96..f7bea4ffbca8b 100644 --- a/crates/forge/tests/cli/eip712.rs +++ b/crates/forge/tests/cli/eip712.rs @@ -1,36 +1,26 @@ use foundry_config::fs_permissions::PathPermission; -const STRUCTS: &str = r#" +forgetest!(test_eip712, |prj, cmd| { + let path = prj + .add_source( + "Structs", + r#" library Structs { - struct Foo { - Bar bar; - } - struct Bar { - Art art; - } - struct Art { - uint256 id; - } + struct Foo { Bar bar; } + struct Bar { Art art; } + struct Art { uint256 id; } struct Complex { Structs2.Foo foo2; Foo[] foos; Rec[][] recs; } - struct Rec { - Rec[] rec; - } + struct Rec { Rec[] rec; } } library Structs2 { - struct Foo { - uint256 id; - } - struct Rec { - Bar[] bar; - } - struct Bar { - Rec rec; - } + struct Foo { uint256 id; } + struct Rec { Bar[] bar; } + struct Bar { Rec rec; } struct FooBar { Foo[] foos; Bar[] bars; @@ -40,10 +30,9 @@ library Structs2 { Structs.Rec rec; } } -"#; - -forgetest!(test_eip712, |prj, cmd| { - let path = prj.add_source("Structs", STRUCTS).unwrap(); + "#, + ) + .unwrap(); cmd.forge_fuse().args(["eip712", path.to_string_lossy().as_ref()]).assert_success().stdout_eq( str![[r#" @@ -65,31 +54,59 @@ 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) - "#]], ); }); -forgetest!(test_eip712_cheacode, |prj, cmd| { - prj.add_source("Structs", STRUCTS).unwrap(); +forgetest!(test_eip712_cheatcode, |prj, cmd| { + prj.add_source( + "Eip712", + r#" +contract Eip712 { + struct Transaction { + Person from; + Person to; + Asset tx; + } + struct Person { + address wallet; + string name; + } + struct Asset { + address token; + uint256 amount; + } +} + "#, + ) + .unwrap(); prj.insert_ds_test(); prj.insert_vm(); + prj.insert_console(); - prj.add_source( - "Eip712Cheat.sol", - r#" + prj.add_source("Eip712Cheat.sol", r#" // Note Used in forge-cli tests to assert failures. // SPDX-License-Identifier: MIT OR Apache-2.0 pragma solidity ^0.8.18; import "./test.sol"; import "./Vm.sol"; +import "./console.sol"; + +string constant CANONICAL = "Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)"; +string constant MESSY = "Person(address wallet, string name) Asset(address token, uint256 amount) Transaction(Person from, Person to, Asset tx)"; contract Eip712Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); - function testReadUtils() public pure { - vm.eip712HashType("Foo_0"); + function testEip712HashType() public { + bytes32 hashCanonical = keccak256(bytes(CANONICAL)); + + bytes32 hashTypeName = vm.eip712HashType("Transaction"); + assertEq(hashTypeName, hashCanonical); + + bytes32 hashTypeDef = vm.eip712HashType(MESSY); + assertEq(hashTypeDef, hashCanonical); } } "#, From d1e1512d6696e1f324660c4e02a6793129e350b2 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Tue, 20 May 2025 10:01:02 -0500 Subject: [PATCH 03/21] finish cheatcode impl + unit tests --- Cargo.lock | 352 ++++++++++++++--------------- Cargo.toml | 2 +- crates/cheatcodes/src/utils.rs | 68 +++--- crates/forge/tests/cli/eip712.rs | 66 ------ crates/forge/tests/cli/test_cmd.rs | 73 ++++++ 5 files changed, 280 insertions(+), 281 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4772a785080e2..c056d8e2a05fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -62,7 +62,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5848366a4f08dca1caca0a6151294a4799fe2e59ba25df100491d92e0b921b1c" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "num_enum", "serde", "strum 0.27.1", @@ -75,7 +75,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681eabb77176be186f3786795a94e6d2465bef9e117b6700ec0e62d39811cc54" dependencies = [ "alloy-eips 1.0.4", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-serde 1.0.4", "alloy-trie", @@ -100,7 +100,7 @@ checksum = "aec7fdaa4f0e4e1ca7e9271ca7887fdd467ca3b9e101582dc6c2bbd1645eae1c" dependencies = [ "alloy-consensus", "alloy-eips 1.0.4", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-serde 1.0.4", "serde", @@ -113,15 +113,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e85622f88139f5da7b5a960ebf4309baf7ccf2a3825fc470e419522231da2eda" dependencies = [ "alloy-consensus", - "alloy-dyn-abi 1.1.0", - "alloy-json-abi 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-json-abi 1.1.2", "alloy-network", "alloy-network-primitives", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-pubsub", "alloy-rpc-types-eth", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "alloy-transport", "futures", "futures-util", @@ -147,16 +147,15 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f90b63261b7744642f6075ed17db6de118eecbe9516ea6c6ffd444b80180b75" +checksum = "18cc14d832bc3331ca22a1c7819de1ede99f58f61a7d123952af7dde8de124a6" dependencies = [ - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", - "alloy-sol-type-parser 1.1.0", - "alloy-sol-types 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", + "alloy-sol-type-parser 1.1.2", + "alloy-sol-types 1.1.2", "arbitrary", - "const-hex", "derive_arbitrary", "derive_more 2.0.1", "itoa", @@ -172,7 +171,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "crc", "serde", @@ -185,7 +184,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "serde", ] @@ -196,7 +195,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "k256", "serde", @@ -212,7 +211,7 @@ dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-serde 0.14.0", "auto_impl", @@ -232,7 +231,7 @@ dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-serde 1.0.4", "auto_impl", @@ -252,8 +251,8 @@ dependencies = [ "alloy-consensus", "alloy-eips 1.0.4", "alloy-hardforks", - "alloy-primitives 1.1.0", - "alloy-sol-types 1.1.0", + "alloy-primitives 1.1.2", + "alloy-sol-types 1.1.2", "auto_impl", "derive_more 2.0.1", "op-alloy-consensus", @@ -269,7 +268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eacc2e22a26b6b5c90bc8db22ca41c4fcd11b1bb2ec6eb47f88299d04d19b1aa" dependencies = [ "alloy-eips 1.0.4", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-serde 1.0.4", "alloy-trie", "serde", @@ -283,7 +282,7 @@ checksum = "b40cc82a2283e3ce6317bc1f0134ea50d20e8c1965393045ee952fb28a65ddbd" dependencies = [ "alloy-chains", "alloy-eip2124", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "auto_impl", "dyn-clone", ] @@ -302,12 +301,12 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0068ae277f5ee3153a95eaea8ff10e188ed8ccde9b7f9926305415a2c0ab2442" +checksum = "3ccaa79753d7bf15f06399ea76922afbfaf8d18bebed9e8fc452984b4a90dcc9" dependencies = [ - "alloy-primitives 1.1.0", - "alloy-sol-type-parser 1.1.0", + "alloy-primitives 1.1.2", + "alloy-sol-type-parser 1.1.2", "serde", "serde_json", ] @@ -318,8 +317,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e8c28ad7af5ae99b0f1983eb601390fa2a972ddaec2b24017d3bdbd4a905bfc" dependencies = [ - "alloy-primitives 1.1.0", - "alloy-sol-types 1.1.0", + "alloy-primitives 1.1.2", + "alloy-sol-types 1.1.2", "serde", "serde_json", "thiserror 2.0.12", @@ -337,12 +336,12 @@ dependencies = [ "alloy-eips 1.0.4", "alloy-json-rpc", "alloy-network-primitives", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types-any", "alloy-rpc-types-eth", "alloy-serde 1.0.4", "alloy-signer", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "async-trait", "auto_impl", "derive_more 2.0.1", @@ -360,7 +359,7 @@ checksum = "5630ce8552579d1393383b27fe4bfe7c700fb7480189a82fc054da24521947aa" dependencies = [ "alloy-consensus", "alloy-eips 1.0.4", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-serde 1.0.4", "serde", ] @@ -375,7 +374,7 @@ dependencies = [ "alloy-eips 1.0.4", "alloy-evm", "alloy-op-hardforks", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "auto_impl", "op-alloy-consensus", "op-revm", @@ -421,9 +420,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a12fe11d0b8118e551c29e1a67ccb6d01cc07ef08086df30f07487146de6fa1" +checksum = "18c35fc4b03ace65001676358ffbbaefe2a2b27ee50fe777c345082c7c888be8" dependencies = [ "alloy-rlp", "arbitrary", @@ -462,7 +461,7 @@ dependencies = [ "alloy-json-rpc", "alloy-network", "alloy-network-primitives", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-pubsub", "alloy-rpc-client", "alloy-rpc-types-debug", @@ -470,7 +469,7 @@ dependencies = [ "alloy-rpc-types-trace", "alloy-rpc-types-txpool", "alloy-signer", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "alloy-transport", "alloy-transport-http", "alloy-transport-ipc", @@ -502,7 +501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78a527d71966a2589c32a555c49ea8919f621c8d85d36bc98bd5a26a66c28163" dependencies = [ "alloy-json-rpc", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-transport", "bimap", "futures", @@ -545,7 +544,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e685b0c1a853afdaf794d634b3f0771be6dcd6539377366239e391e68e1f115" dependencies = [ "alloy-json-rpc", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-pubsub", "alloy-transport", "alloy-transport-http", @@ -572,7 +571,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9052f908df9ffd6e830a841e9a35cb280e27ccc87a493f5621a517c77345153" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types-anvil", "alloy-rpc-types-engine", "alloy-rpc-types-eth", @@ -588,7 +587,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ebe3dcbc6c85678f29c205b2fcf6b110b32287bf6b72bbee37ed9011404e926" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types-eth", "alloy-serde 1.0.4", "serde", @@ -611,7 +610,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7913c67b874db23446a4cdd020da1bbc828513bd83536ccabfca403b71cdeaf9" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "serde", ] @@ -623,7 +622,7 @@ checksum = "63b70151dc3282ce4bbde31b80a7f0f1e53b9dec9b187f528394e8f0a0411975" dependencies = [ "alloy-consensus", "alloy-eips 1.0.4", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-serde 1.0.4", "derive_more 2.0.1", @@ -643,10 +642,10 @@ dependencies = [ "alloy-consensus-any", "alloy-eips 1.0.4", "alloy-network-primitives", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-serde 1.0.4", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "itertools 0.14.0", "serde", "serde_json", @@ -659,7 +658,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcf555fe777cf7d11b8ebe837aca0b0ceb74f1ed9937f938b8c9fbd1460994cf" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types-eth", "alloy-serde 1.0.4", "serde", @@ -673,7 +672,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87c69ea401ce851b52c9b07d838173cd3c23c11a552a5e5ddde3ffd834647a46" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types-eth", "alloy-serde 1.0.4", "serde", @@ -685,7 +684,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4dba6ff08916bc0a9cbba121ce21f67c0b554c39cf174bc7b9df6c651bd3c3b" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "serde", "serde_json", ] @@ -696,7 +695,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e22b9437fededfd5371968129381e9a00c3d2d8fff9846b1de3d1625fd307c" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "serde", "serde_json", ] @@ -707,9 +706,9 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c32a4ee33852817fe852c856d68f326980b3776e0d55d51ff9535b5a5945e68" dependencies = [ - "alloy-dyn-abi 1.1.0", - "alloy-primitives 1.1.0", - "alloy-sol-types 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-primitives 1.1.2", + "alloy-sol-types 1.1.2", "async-trait", "auto_impl", "either", @@ -726,7 +725,7 @@ checksum = "0946c9082fe664b5a60f8451a75aafb04e6d5893c99ae92446fbba45d2d5dc09" dependencies = [ "alloy-consensus", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-signer", "async-trait", "aws-sdk-kms", @@ -744,7 +743,7 @@ checksum = "be3bd4d17c3e59ac664f215369b6d2d4ee51fe2f31aae6015bf220ce2ffd03d9" dependencies = [ "alloy-consensus", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-signer", "async-trait", "gcloud-sdk", @@ -761,11 +760,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fcb32ccedb85055969c8161a3abc2e73b0af7b1f9e800ff494dfc4a663b24b" dependencies = [ "alloy-consensus", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-signer", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "async-trait", "coins-ledger", "futures-util", @@ -782,7 +781,7 @@ checksum = "838b02f438365a5fecca1a736968680cedf2b309fcb96dfcc5ab2560d74533da" dependencies = [ "alloy-consensus", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-signer", "async-trait", "coins-bip32", @@ -801,7 +800,7 @@ checksum = "b97e3d7211e1abcc3fd4e5e7dfe90eb6ff733efc3102386341c121a75cd179b5" dependencies = [ "alloy-consensus", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-signer", "async-trait", "semver 1.0.26", @@ -826,12 +825,12 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d3ef8e0d622453d969ba3cded54cf6800efdc85cb929fe22c5bdf8335666757" +checksum = "8612e0658964d616344f199ab251a49d48113992d81b92dab93ed855faa66383" dependencies = [ - "alloy-sol-macro-expander 1.1.0", - "alloy-sol-macro-input 1.1.0", + "alloy-sol-macro-expander 1.1.2", + "alloy-sol-macro-input 1.1.2", "proc-macro-error2", "proc-macro2", "quote", @@ -858,12 +857,12 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0e84bd0693c69a8fbe3ec0008465e029c6293494df7cb07580bf4a33eff52e1" +checksum = "7a384edac7283bc4c010a355fb648082860c04b826bb7a814c45263c8f304c74" dependencies = [ - "alloy-json-abi 1.1.0", - "alloy-sol-macro-input 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-sol-macro-input 1.1.2", "const-hex", "heck", "indexmap 2.9.0", @@ -871,7 +870,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.101", - "syn-solidity 1.1.0", + "syn-solidity 1.1.2", "tiny-keccak", ] @@ -893,11 +892,11 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3de663412dadf9b64f4f92f507f78deebcc92339d12cf15f88ded65d41c7935" +checksum = "0dd588c2d516da7deb421b8c166dc60b7ae31bca5beea29ab6621fcfa53d6ca5" dependencies = [ - "alloy-json-abi 1.1.0", + "alloy-json-abi 1.1.2", "const-hex", "dunce", "heck", @@ -906,7 +905,7 @@ dependencies = [ "quote", "serde_json", "syn 2.0.101", - "syn-solidity 1.1.0", + "syn-solidity 1.1.2", ] [[package]] @@ -921,9 +920,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "251273c5aa1abb590852f795c938730fa641832fc8fa77b5478ed1bf11b6097e" +checksum = "e86ddeb70792c7ceaad23e57d52250107ebbb86733e52f4a25d8dc1abc931837" dependencies = [ "serde", "winnow", @@ -944,14 +943,13 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5460a975434ae594fe2b91586253c1beb404353b78f0a55bf124abcd79557b15" +checksum = "584cb97bfc5746cb9dcc4def77da11694b5d6d7339be91b7480a6a68dc129387" dependencies = [ - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", - "alloy-sol-macro 1.1.0", - "const-hex", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", + "alloy-sol-macro 1.1.2", "serde", ] @@ -962,7 +960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efc04c8732bae7f87bc4483fd377045a4295eccaf253860a8c6660a896e2befc" dependencies = [ "alloy-json-rpc", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "base64 0.22.1", "derive_more 2.0.1", "futures", @@ -1037,7 +1035,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "983d99aa81f586cef9dae38443245e585840fcf0fc58b09aee0b1f27aed1d500" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "arrayvec", "derive_more 2.0.1", @@ -1165,13 +1163,13 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-contract", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-eips 1.0.4", "alloy-evm", "alloy-genesis", "alloy-network", "alloy-op-evm", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-pubsub", "alloy-rlp", @@ -1179,7 +1177,7 @@ dependencies = [ "alloy-serde 1.0.4", "alloy-signer", "alloy-signer-local", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "alloy-transport", "alloy-trie", "anvil-core", @@ -1227,10 +1225,10 @@ name = "anvil-core" version = "1.2.0" dependencies = [ "alloy-consensus", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-eips 1.0.4", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-rpc-types", "alloy-serde 1.0.4", @@ -2463,18 +2461,18 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-contract", - "alloy-dyn-abi 1.1.0", - "alloy-json-abi 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-json-abi 1.1.2", "alloy-json-rpc", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rlp", "alloy-rpc-types", "alloy-serde 1.0.4", "alloy-signer", "alloy-signer-local", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "alloy-transport", "anvil", "aws-sdk-kms", @@ -2558,9 +2556,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" name = "chisel" version = "1.2.0" dependencies = [ - "alloy-dyn-abi 1.1.0", - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "clap", "dirs", "eyre", @@ -3658,7 +3656,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3864,10 +3862,10 @@ name = "forge" version = "1.2.0" dependencies = [ "alloy-chains", - "alloy-dyn-abi 1.1.0", - "alloy-json-abi 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-json-abi 1.1.2", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rpc-types", "alloy-serde 1.0.4", @@ -3947,7 +3945,7 @@ dependencies = [ name = "forge-doc" version = "1.2.0" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "derive_more 2.0.1", "eyre", "forge-fmt", @@ -3970,7 +3968,7 @@ dependencies = [ name = "forge-fmt" version = "1.2.0" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "ariadne", "foundry-config", "foundry-solang-parser", @@ -3988,11 +3986,11 @@ version = "1.2.0" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-eips 1.0.4", - "alloy-json-abi 1.1.0", + "alloy-json-abi 1.1.2", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rpc-types", "alloy-serde 1.0.4", @@ -4032,7 +4030,7 @@ name = "forge-script-sequence" version = "1.2.0" dependencies = [ "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "eyre", "foundry-common", "foundry-compilers", @@ -4047,8 +4045,8 @@ dependencies = [ name = "forge-sol-macro-gen" version = "1.2.0" dependencies = [ - "alloy-sol-macro-expander 1.1.0", - "alloy-sol-macro-input 1.1.0", + "alloy-sol-macro-expander 1.1.2", + "alloy-sol-macro-input 1.1.2", "eyre", "foundry-common", "prettyplease", @@ -4062,9 +4060,9 @@ dependencies = [ name = "forge-verify" version = "1.2.0" dependencies = [ - "alloy-dyn-abi 1.1.0", - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rpc-types", "async-trait", @@ -4108,8 +4106,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6129df264d2bd245ade4ed21a92f605bfd592dca8fb8e6e1adde1b9bd4288681" dependencies = [ "alloy-chains", - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "foundry-compilers", "reqwest", "semver 1.0.26", @@ -4125,18 +4123,18 @@ version = "1.2.0" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-evm", "alloy-genesis", - "alloy-json-abi 1.1.0", + "alloy-json-abi 1.1.2", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rlp", "alloy-rpc-types", "alloy-signer", "alloy-signer-local", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "base64 0.22.1", "dialoguer", "ecdsa", @@ -4173,7 +4171,7 @@ dependencies = [ name = "foundry-cheatcodes-spec" version = "1.2.0" dependencies = [ - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "foundry-macros", "schemars", "serde", @@ -4185,10 +4183,10 @@ name = "foundry-cli" version = "1.2.0" dependencies = [ "alloy-chains", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-eips 1.0.4", - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rlp", "cfg-if", @@ -4233,18 +4231,18 @@ version = "1.2.0" dependencies = [ "alloy-consensus", "alloy-contract", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-eips 1.0.4", - "alloy-json-abi 1.1.0", + "alloy-json-abi 1.1.2", "alloy-json-rpc", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-pubsub", "alloy-rpc-client", "alloy-rpc-types", "alloy-serde 1.0.4", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "alloy-transport", "alloy-transport-http", "alloy-transport-ipc", @@ -4289,9 +4287,9 @@ name = "foundry-common-fmt" version = "1.2.0" dependencies = [ "alloy-consensus", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types", "alloy-serde 1.0.4", "chrono", @@ -4310,8 +4308,8 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6154e503612a175a88ff342592f0a44664dda54a508d9443121b62b1701f91" dependencies = [ - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "auto_impl", "derive_more 1.0.0", "dirs", @@ -4357,8 +4355,8 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a3ffc93f94d2c4ae0ff0f7a12cdeaa5fbb043ced0c558cabd05631e32ac508a" dependencies = [ - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "foundry-compilers-core", "futures-util", "path-slash", @@ -4380,8 +4378,8 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f077777aa33f933f9f01e90f9ed78e4a40ed60a6380798b528681ca9519a577" dependencies = [ - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "foundry-compilers-artifacts-solc", "foundry-compilers-core", "path-slash", @@ -4395,7 +4393,7 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ff92d5831075077fe64391dcbbe4a1518bce0439f97ab6a940fa1b9c1f3eaa2" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "cfg-if", "dunce", "fs_extra", @@ -4417,7 +4415,7 @@ name = "foundry-config" version = "1.2.0" dependencies = [ "alloy-chains", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "dirs", "dunce", "eyre", @@ -4453,7 +4451,7 @@ dependencies = [ name = "foundry-debugger" version = "1.2.0" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "crossterm", "eyre", "foundry-common", @@ -4471,11 +4469,11 @@ dependencies = [ name = "foundry-evm" version = "1.2.0" dependencies = [ - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-evm", - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", - "alloy-sol-types 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", + "alloy-sol-types 1.1.2", "eyre", "foundry-cheatcodes", "foundry-common", @@ -4499,8 +4497,8 @@ dependencies = [ name = "foundry-evm-abi" version = "1.2.0" dependencies = [ - "alloy-primitives 1.1.0", - "alloy-sol-types 1.1.0", + "alloy-primitives 1.1.2", + "alloy-sol-types 1.1.2", "derive_more 2.0.1", "foundry-common-fmt", "foundry-macros", @@ -4512,16 +4510,16 @@ name = "foundry-evm-core" version = "1.2.0" dependencies = [ "alloy-consensus", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-evm", "alloy-genesis", - "alloy-json-abi 1.1.0", + "alloy-json-abi 1.1.2", "alloy-network", "alloy-op-evm", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rpc-types", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "auto_impl", "eyre", "foundry-cheatcodes-spec", @@ -4548,7 +4546,7 @@ dependencies = [ name = "foundry-evm-coverage" version = "1.2.0" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "eyre", "foundry-common", "foundry-compilers", @@ -4563,9 +4561,9 @@ dependencies = [ name = "foundry-evm-fuzz" version = "1.2.0" dependencies = [ - "alloy-dyn-abi 1.1.0", - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "eyre", "foundry-common", "foundry-compilers", @@ -4587,10 +4585,10 @@ dependencies = [ name = "foundry-evm-traces" version = "1.2.0" dependencies = [ - "alloy-dyn-abi 1.1.0", - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", - "alloy-sol-types 1.1.0", + "alloy-dyn-abi 1.1.2", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", + "alloy-sol-types 1.1.2", "eyre", "foundry-block-explorers", "foundry-common", @@ -4618,7 +4616,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c99831be91edd8a025fa60443b5404ad407708bc337d2e20440d498b5806fab8" dependencies = [ "alloy-consensus", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "alloy-rpc-types", "eyre", @@ -4637,7 +4635,7 @@ dependencies = [ name = "foundry-linking" version = "1.2.0" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "foundry-compilers", "semver 1.0.26", "thiserror 2.0.12", @@ -4671,7 +4669,7 @@ dependencies = [ name = "foundry-test-utils" version = "1.2.0" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-provider", "eyre", "fd-lock", @@ -4697,16 +4695,16 @@ name = "foundry-wallets" version = "1.2.0" dependencies = [ "alloy-consensus", - "alloy-dyn-abi 1.1.0", + "alloy-dyn-abi 1.1.2", "alloy-network", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-signer", "alloy-signer-aws", "alloy-signer-gcp", "alloy-signer-ledger", "alloy-signer-local", "alloy-signer-trezor", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "async-trait", "aws-config", "aws-sdk-kms", @@ -5532,7 +5530,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi 0.5.1", "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5595,7 +5593,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6525,7 +6523,7 @@ checksum = "6f318b09e24148f07392c5e011bae047a0043851f9041145df5f3b01e4fedd1e" dependencies = [ "alloy-consensus", "alloy-eips 1.0.4", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rlp", "alloy-serde 1.0.4", "derive_more 2.0.1", @@ -6542,7 +6540,7 @@ dependencies = [ "alloy-consensus", "alloy-eips 1.0.4", "alloy-network-primitives", - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types-eth", "alloy-serde 1.0.4", "derive_more 2.0.1", @@ -7296,7 +7294,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7694,10 +7692,10 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f847f5e88a09ac84b36529fbe2fee80b3d8bbf91e9a7ae3ea856c4125d0d232" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "alloy-rpc-types-eth", "alloy-rpc-types-trace", - "alloy-sol-types 1.1.0", + "alloy-sol-types 1.1.2", "anstyle", "colorchoice", "revm", @@ -7746,7 +7744,7 @@ name = "revm-primitives" version = "19.0.0" source = "git+https://github.com/bluealloy/revm.git?rev=b5808253#b580825320708f0c47d3734ceab03d90c0b11ba1" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "num_enum", "serde", ] @@ -7934,7 +7932,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -7947,7 +7945,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -8605,7 +8603,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7960f42b73c63b78df9e223ea88ca87b7aaef91e3b5084b89d79ec31ad9fc8e3" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "bumpalo", "either", "num-bigint", @@ -8665,7 +8663,7 @@ dependencies = [ "solar-config", "solar-data-structures", "solar-macros", - "thiserror 1.0.69", + "thiserror 2.0.12", "tracing", "unicode-width 0.2.0", ] @@ -8687,7 +8685,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7965e27a45ca85135ffd45839f9623131175fb43d2ad3526d32de0946f250f1b" dependencies = [ - "alloy-primitives 1.1.0", + "alloy-primitives 1.1.2", "bitflags 2.9.1", "bumpalo", "itertools 0.14.0", @@ -8708,8 +8706,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7e695824aaf984aa01493ebd5e7e83ddf84629d4a2667a0adf25cb6b65fa63e" dependencies = [ - "alloy-json-abi 1.1.0", - "alloy-primitives 1.1.0", + "alloy-json-abi 1.1.2", + "alloy-primitives 1.1.2", "bitflags 2.9.1", "bumpalo", "derive_more 2.0.1", @@ -8991,7 +8989,7 @@ dependencies = [ "serde_json", "sha2 0.10.9", "tempfile", - "thiserror 1.0.69", + "thiserror 2.0.12", "url", "zip", ] @@ -9044,9 +9042,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0f0d4760f4c2a0823063b2c70e97aa2ad185f57be195172ccc0e23c4b787c4" +checksum = "1b5d879005cc1b5ba4e18665be9e9501d9da3a9b95f625497c4cb7ee082b532e" dependencies = [ "paste", "proc-macro2", @@ -10283,7 +10281,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index febe1911fd141..b9eed6076d38c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -229,7 +229,7 @@ alloy-transport-ipc = { version = "1.0.3", default-features = false } alloy-transport-ws = { version = "1.0.3", default-features = false } ## alloy-core -alloy-dyn-abi = "1.0" +alloy-dyn-abi = "1.1.2" alloy-json-abi = "1.0" alloy-primitives = { version = "1.0", features = [ "getrandom", diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index ea9a3163b7053..3f03f6ccd792d 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -1,7 +1,7 @@ //! Implementations of [`Utilities`](spec::Group::Utilities) cheatcodes. use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; -use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue, Resolver}; +use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue}; use alloy_primitives::{aliases::B32, keccak256, map::HashMap, B64, U256}; use alloy_sol_types::SolValue; use foundry_common::{ens::namehash, fs}; @@ -316,57 +316,51 @@ fn random_int(state: &mut Cheatcodes, bits: Option) -> Result { .abi_encode()) } -// `string contant schema_Foo = "Foo(bar uin256)";` -const TYPE_BINDING_PREFIX: &str = "string constant schema_"; - impl Cheatcode for eip712HashTypeCall { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self { typeDefinition } = self; let type_def = if !typeDefinition.contains('(') { - &get_type_def_from_bindings(typeDefinition, state)? + get_type_def_from_bindings(typeDefinition, state)? } else { - typeDefinition - // let canonical = EncodeType::parse(typeDefinition).and_then(|parsed| - // parsed.canonicalize())?; + EncodeType::parse(&typeDefinition).and_then(|parsed| parsed.canonicalize())? }; - // let hash = keccak256(type_def.as_bytes()); - // bail!("type: {type_def}, hash: {hash}"); Ok(keccak256(type_def.as_bytes()).to_vec()) } } fn get_type_def_from_bindings(name: &String, state: &mut Cheatcodes) -> Result { - let path = state.config.ensure_path_allowed( - &state.config.root.join("utils").join("JsonBindings.sol"), - FsAccessKind::Read, - )?; - - let content = fs::read_to_string(path)?; - - let mut type_defs = HashMap::new(); - for line in content.lines() { - let line = line.trim(); - if !line.starts_with(TYPE_BINDING_PREFIX) { - continue; - } - - let relevant = &line[TYPE_BINDING_PREFIX.len()..]; - if let Some(idx) = relevant.find('=') { - let name = relevant[..idx].trim(); - - // relevant value chars are " \"Foo(bar uint256)\";" - let def = relevant[idx + 1..].trim(); - if def.len() > 3 && def.starts_with('"') && def.ends_with("\";") { - let value = &def[1..def.len() - 2]; - type_defs.insert(name, value); - } - } - } + const TYPE_BINDING_PREFIX: &str = "string constant schema_"; + + let path = state.config.root.join("utils").join("JsonBindings.sol"); + let path = state.config.ensure_path_allowed(&path, FsAccessKind::Read)?; + let content = fs::read_to_string(&path)?; + + let type_defs: HashMap<&str, &str> = content + .lines() + .filter_map(|line| { + let relevant = line.trim().strip_prefix(TYPE_BINDING_PREFIX)?; + let (name, def) = relevant.split_once('=')?; + Some((name.trim(), def.trim().strip_prefix('"')?.strip_suffix("\";")?)) + }) + .collect(); match type_defs.get(name.as_str()) { Some(value) => Ok(value.to_string()), - None => bail!(format!("'{name}' not found in 'utils/JsonBindings.sol'\n{:#?}", type_defs)), + None => { + let bindings = + type_defs.keys().map(|k| format!(" - {k}")).collect::>().join("\n"); + + bail!( + "'{}' not found in 'utils/JsonBindings.sol'.{}", + name, + if bindings.is_empty() { + String::new() + } else { + format!("\nAvailable bindings:\n{}\n", bindings) + } + ); + } } } diff --git a/crates/forge/tests/cli/eip712.rs b/crates/forge/tests/cli/eip712.rs index f7bea4ffbca8b..55d40474e3d81 100644 --- a/crates/forge/tests/cli/eip712.rs +++ b/crates/forge/tests/cli/eip712.rs @@ -1,5 +1,3 @@ -use foundry_config::fs_permissions::PathPermission; - forgetest!(test_eip712, |prj, cmd| { let path = prj .add_source( @@ -57,67 +55,3 @@ FooBar(Foo[] foos,Bar[] bars,Foo_1 foo,Bar_1 bar,Rec[] recs,Rec_1 rec)Art(uint25 "#]], ); }); - -forgetest!(test_eip712_cheatcode, |prj, cmd| { - prj.add_source( - "Eip712", - r#" -contract Eip712 { - struct Transaction { - Person from; - Person to; - Asset tx; - } - struct Person { - address wallet; - string name; - } - struct Asset { - address token; - uint256 amount; - } -} - "#, - ) - .unwrap(); - prj.insert_ds_test(); - prj.insert_vm(); - prj.insert_console(); - - prj.add_source("Eip712Cheat.sol", r#" -// Note Used in forge-cli tests to assert failures. -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - -import "./test.sol"; -import "./Vm.sol"; -import "./console.sol"; - -string constant CANONICAL = "Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)"; -string constant MESSY = "Person(address wallet, string name) Asset(address token, uint256 amount) Transaction(Person from, Person to, Asset tx)"; - -contract Eip712Test is DSTest { - Vm constant vm = Vm(HEVM_ADDRESS); - - function testEip712HashType() public { - bytes32 hashCanonical = keccak256(bytes(CANONICAL)); - - bytes32 hashTypeName = vm.eip712HashType("Transaction"); - assertEq(hashTypeName, hashCanonical); - - bytes32 hashTypeDef = vm.eip712HashType(MESSY); - assertEq(hashTypeDef, hashCanonical); - } -} -"#, - ) - .unwrap(); - - cmd.forge_fuse().args(["bind-json"]).assert_success(); - - let bindings = prj.root().join("utils").join("JsonBindings.sol"); - assert!(bindings.exists(), "JsonBindings.sol was not generated at {:?}", bindings); - - prj.update_config(|config| config.fs_permissions.add(PathPermission::read(bindings))); - cmd.forge_fuse().args(["test", "--mc", "Eip712Test", "-vvvv"]).assert_success(); -}); diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 6a75e4478bf3d..ebbee81af738f 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -2,6 +2,7 @@ use alloy_primitives::U256; use anvil::{spawn, NodeConfig}; +use foundry_config::fs_permissions::PathPermission; use foundry_test_utils::{ rpc, str, util::{OutputExt, OTHER_SOLC_VERSION, SOLC_VERSION}, @@ -3649,3 +3650,75 @@ Encountered a total of 1 failing tests, 0 tests succeeded "#]]); }); + +forgetest!(test_eip712_cheatcode, |prj, cmd| { + prj.add_source( + "Eip712", + r#" +contract Eip712Structs { + struct Transaction { + Person from; + Person to; + Asset tx; + } + struct Person { + address wallet; + string name; + } + struct Asset { + address token; + uint256 amount; + } +} + "#, + ) + .unwrap(); + prj.insert_ds_test(); + prj.insert_vm(); + prj.insert_console(); + + prj.add_source("Eip712Cheat.sol", r#" +// Note Used in forge-cli tests to assert failures. +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.18; + +import "./test.sol"; +import "./Vm.sol"; +import "./console.sol"; + +string constant CANONICAL = "Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)"; + +contract Eip712Test is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testEip712HashType() public { + bytes32 canonicalHash = keccak256(bytes(CANONICAL)); + + // Can figure out the canonical type from a messy string representation of the type, + // with an invalid order and extra whitespaces + bytes32 fromTypeDef = vm.eip712HashType( + "Person(address wallet, string name) Asset(address token, uint256 amount) Transaction(Person from, Person to, Asset tx)" + ); + assertEq(fromTypeDef, canonicalHash); + + // Can figure out the canonical type from the previously generated bindings + bytes32 fromTypeName = vm.eip712HashType("Transaction"); + assertEq(fromTypeName, canonicalHash); + + // Reverts if the input type is not found in the bindings + vm._expectCheatcodeRevert(); + fromTypeName = vm.eip712HashType("InvalidTypeName"); + } +} +"#, + ) + .unwrap(); + + cmd.forge_fuse().args(["bind-json"]).assert_success(); + + let bindings = prj.root().join("utils").join("JsonBindings.sol"); + assert!(bindings.exists(), "'JsonBindings.sol' was not generated at {:?}", bindings); + + prj.update_config(|config| config.fs_permissions.add(PathPermission::read(bindings))); + cmd.forge_fuse().args(["test", "--mc", "Eip712Test", "-vvvv"]).assert_success(); +}); From cf67c2cc4c0089383a1efc5e78b75f6e11724c81 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Tue, 20 May 2025 11:15:36 -0500 Subject: [PATCH 04/21] style: clippy + fmt --- crates/cheatcodes/src/utils.rs | 4 ++-- crates/forge/tests/cli/eip712.rs | 32 +++++++++++++++++++++--------- crates/forge/tests/cli/test_cmd.rs | 2 +- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 3f03f6ccd792d..4ca22fb9ada3a 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -323,7 +323,7 @@ impl Cheatcode for eip712HashTypeCall { let type_def = if !typeDefinition.contains('(') { get_type_def_from_bindings(typeDefinition, state)? } else { - EncodeType::parse(&typeDefinition).and_then(|parsed| parsed.canonicalize())? + EncodeType::parse(typeDefinition).and_then(|parsed| parsed.canonicalize())? }; Ok(keccak256(type_def.as_bytes()).to_vec()) @@ -358,7 +358,7 @@ fn get_type_def_from_bindings(name: &String, state: &mut Cheatcodes) -> Result Date: Tue, 20 May 2025 12:32:29 -0500 Subject: [PATCH 05/21] fix: simple example + bump alloy core + docs --- Cargo.toml | 11 ++-- crates/cheatcodes/spec/src/vm.rs | 7 ++- crates/forge/tests/cli/test_cmd.rs | 81 +++++++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4c36858f48ec4..3f6b61fe09bdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -196,7 +196,6 @@ foundry-wallets = { path = "crates/wallets" } foundry-linking = { path = "crates/linking" } # solc & compilation utilities - foundry-block-explorers = { version = "0.17.0", default-features = false } foundry-compilers = { version = "0.16.1", default-features = false } foundry-fork-db = "0.14" @@ -230,16 +229,16 @@ alloy-transport-ws = { version = "1.0.5", default-features = false } ## alloy-core alloy-dyn-abi = "1.1.2" -alloy-json-abi = "1.0" -alloy-primitives = { version = "1.0", features = [ +alloy-json-abi = "1.1.2" +alloy-primitives = { version = "1.1.2", features = [ "getrandom", "rand", "map-fxhash", "map-foldhash", ] } -alloy-sol-macro-expander = "1.0" -alloy-sol-macro-input = "1.0" -alloy-sol-types = "1.0" +alloy-sol-macro-expander = "1.1.2" +alloy-sol-macro-input = "1.1.2" +alloy-sol-types = "1.1.2" alloy-chains = "0.2" alloy-rlp = "0.3" diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 2d9a61d9c829e..0ffa5259afbd2 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -2889,7 +2889,12 @@ interface Vm { #[cheatcode(group = Utilities, safety = Unsafe)] function interceptInitcode() external; - /// Randomly shuffles an array. + /// Generates the hash of the canonical EIP-712 type representation. + /// + /// Supports 2 different inputs: + /// * Name of the type (i.e. "Transaction") --> requires previous binding generation with `forge bind-json` + /// * String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)") --> the cheatcode + /// will output the canonical type even if the input is malformated (wrong order or whitespaces) #[cheatcode(group = Utilities)] function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash); } diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 24df946ddb8a5..9a4e0e76d0190 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3651,7 +3651,81 @@ Encountered a total of 1 failing tests, 0 tests succeeded "#]]); }); -forgetest!(test_eip712_cheatcode, |prj, cmd| { +forgetest!(test_eip712_cheatcode_simple, |prj, cmd| { + prj.add_source( + "Eip712", + r#" +contract Eip712Structs { + struct EIP712Domain { + string name; + string version; + uint256 chainId; + address verifyingContract; + } +} + "#, + ) + .unwrap(); + prj.insert_ds_test(); + prj.insert_vm(); + prj.insert_console(); + + prj.add_source("Eip712Cheat.sol", r#" +import "./test.sol"; +import "./Vm.sol"; +import "./console.sol"; + +string constant CANONICAL = "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"; + +contract Eip712Test is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testEip712HashType() public { + bytes32 canonicalHash = keccak256(bytes(CANONICAL)); + console.logBytes32(canonicalHash); + + // Can figure out the canonical type from a messy string representation of the type, + // with an invalid order and extra whitespaces + bytes32 fromTypeDef = vm.eip712HashType( + "EIP712Domain(string name, string version, uint256 chainId, address verifyingContract)" + ); + assertEq(fromTypeDef, canonicalHash); + + // Can figure out the canonical type from the previously generated bindings + bytes32 fromTypeName = vm.eip712HashType("EIP712Domain"); + assertEq(fromTypeName, canonicalHash); + } +} +"#, + ) + .unwrap(); + + cmd.forge_fuse().args(["bind-json"]).assert_success(); + + let bindings = prj.root().join("utils").join("JsonBindings.sol"); + assert!(bindings.exists(), "'JsonBindings.sol' was not generated at {bindings:?}"); + + prj.update_config(|config| config.fs_permissions.add(PathPermission::read(bindings))); + cmd.forge_fuse().args(["test", "--mc", "Eip712Test", "-vv"]).assert_success().stdout_eq(str![ + [r#" +[COMPILING_FILES] with [SOLC_VERSION] +[SOLC_VERSION] [ELAPSED] +Compiler run successful! + +Ran 1 test for src/Eip712Cheat.sol:Eip712Test +[PASS] testEip712HashType() ([GAS]) +Logs: + 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f + +Suite result: ok. 1 passed; 0 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 1 tests passed, 0 failed, 0 skipped (1 total tests) + +"#] + ]); +}); + +forgetest!(test_eip712_cheatcode_nested, |prj, cmd| { prj.add_source( "Eip712", r#" @@ -3678,13 +3752,8 @@ contract Eip712Structs { prj.insert_console(); prj.add_source("Eip712Cheat.sol", r#" -// Note Used in forge-cli tests to assert failures. -// SPDX-License-Identifier: MIT OR Apache-2.0 -pragma solidity ^0.8.18; - import "./test.sol"; import "./Vm.sol"; -import "./console.sol"; string constant CANONICAL = "Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)"; From a6cca9a47360fbdc75c0583bfdeba99494da7227 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Tue, 20 May 2025 15:08:24 -0500 Subject: [PATCH 06/21] fix: cheats spec --- crates/cheatcodes/assets/cheatcodes.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 4d5d35ab05953..595c6d23ad581 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -4297,7 +4297,7 @@ { "func": { "id": "eip712HashType", - "description": "Randomly shuffles an array.", + "description": "Generates the hash of the canonical EIP-712 type representation.\nSupports 2 different inputs:\n * Name of the type (i.e. \"Transaction\") --> requires previous binding generation with `forge bind-json`\n * String representation of the type (i.e. \"Foo(Bar bar) Bar(uint256 baz)\") --> the cheatcode\n will output the canonical type even if the input is malformated (wrong order or whitespaces)", "declaration": "function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash);", "visibility": "external", "mutability": "pure", From 4395b32669dca0e61c875dab2575c5275f2d9f2a Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 22 May 2025 09:11:56 -0500 Subject: [PATCH 07/21] load json bindings from foundry.toml + allow custom path + extend tests --- crates/cheatcodes/assets/cheatcodes.json | 26 +++++++++++-- crates/cheatcodes/spec/src/vm.rs | 21 +++++++++-- crates/cheatcodes/src/config.rs | 4 ++ crates/cheatcodes/src/utils.rs | 38 +++++++++++++------ crates/common/src/constants.rs | 3 ++ crates/forge/src/cmd/bind_json.rs | 6 +-- crates/forge/tests/cli/test_cmd.rs | 48 +++++++++++++++++++++--- testdata/cheats/Vm.sol | 3 +- 8 files changed, 122 insertions(+), 27 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 595c6d23ad581..7e903135a897a 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -4296,9 +4296,9 @@ }, { "func": { - "id": "eip712HashType", - "description": "Generates the hash of the canonical EIP-712 type representation.\nSupports 2 different inputs:\n * Name of the type (i.e. \"Transaction\") --> requires previous binding generation with `forge bind-json`\n * String representation of the type (i.e. \"Foo(Bar bar) Bar(uint256 baz)\") --> the cheatcode\n will output the canonical type even if the input is malformated (wrong order or whitespaces)", - "declaration": "function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash);", + "id": "eip712HashType_0", + "description": "Generates the hash of the canonical EIP-712 type representation.\nSupports 2 different inputs:\n 1. Name of the type (i.e. \"Transaction\"):\n * requires previous binding generation with `forge bind-json`.\n * bindings will be retrieved from the path configured in `foundry.toml`.\n 2. String representation of the type (i.e. \"Foo(Bar bar) Bar(uint256 baz)\").\n * Note: the cheatcode will output the canonical type even if the input is malformated\n with the wrong order of elements or with extra whitespaces.", + "declaration": "function eip712HashType(string memory typeNameOrDefinition) external pure returns (bytes32 typeHash);", "visibility": "external", "mutability": "pure", "signature": "eip712HashType(string)", @@ -4314,6 +4314,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "eip712HashType_1", + "description": "Generates the hash of the canonical EIP-712 type representation.\nRequires previous binding generation with `forge bind-json`.\nParams:\n * `bindingsPath`: path where the output of `forge bind-json` is stored.\n * `typeName`: Name of the type (i.e. \"Transaction\").", + "declaration": "function eip712HashType(string calldata bindingsPath, string memory typeName) external pure returns (bytes32 typeHash);", + "visibility": "external", + "mutability": "pure", + "signature": "eip712HashType(string,string)", + "selector": "0x18fb6406", + "selectorBytes": [ + 24, + 251, + 100, + 6 + ] + }, + "group": "utilities", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "ensNamehash", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 0ffa5259afbd2..025311768e67c 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -2892,11 +2892,24 @@ interface Vm { /// Generates the hash of the canonical EIP-712 type representation. /// /// Supports 2 different inputs: - /// * Name of the type (i.e. "Transaction") --> requires previous binding generation with `forge bind-json` - /// * String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)") --> the cheatcode - /// will output the canonical type even if the input is malformated (wrong order or whitespaces) + /// 1. Name of the type (i.e. "Transaction"): + /// * requires previous binding generation with `forge bind-json`. + /// * bindings will be retrieved from the path configured in `foundry.toml`. + /// + /// 2. String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)"). + /// * Note: the cheatcode will output the canonical type even if the input is malformated + /// with the wrong order of elements or with extra whitespaces. + #[cheatcode(group = Utilities)] + function eip712HashType(string memory typeNameOrDefinition) external pure returns (bytes32 typeHash); + + /// Generates the hash of the canonical EIP-712 type representation. + /// Requires previous binding generation with `forge bind-json`. + /// + /// Params: + /// * `bindingsPath`: path where the output of `forge bind-json` is stored. + /// * `typeName`: Name of the type (i.e. "Transaction"). #[cheatcode(group = Utilities)] - function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash); + function eip712HashType(string calldata bindingsPath, string memory typeName) external pure returns (bytes32 typeHash); } } diff --git a/crates/cheatcodes/src/config.rs b/crates/cheatcodes/src/config.rs index 210c76553cba7..1ad98cd93e92b 100644 --- a/crates/cheatcodes/src/config.rs +++ b/crates/cheatcodes/src/config.rs @@ -33,6 +33,8 @@ pub struct CheatsConfig { pub rpc_endpoints: ResolvedRpcEndpoints, /// Project's paths as configured pub paths: ProjectPathsConfig, + /// Path to the directory that contains the bindings generated by `forge bind-json`. + pub bind_json_path: PathBuf, /// Filesystem permissions for cheatcodes like `writeFile`, `readFile` pub fs_permissions: FsPermissions, /// Project root @@ -98,6 +100,7 @@ impl CheatsConfig { no_storage_caching: config.no_storage_caching, rpc_endpoints, paths: config.project_paths(), + bind_json_path: config.bind_json.out.clone(), fs_permissions: config.fs_permissions.clone().joined(config.root.as_ref()), root: config.root.clone(), broadcast: config.root.clone().join(&config.broadcast), @@ -303,6 +306,7 @@ impl Default for CheatsConfig { paths: ProjectPathsConfig::builder().build_with_root("./"), fs_permissions: Default::default(), root: Default::default(), + bind_json_path: PathBuf::default().join("utils").join("jsonBindings.sol"), broadcast: Default::default(), allowed_paths: vec![], evm_opts: Default::default(), diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 4ca22fb9ada3a..8f0ebb44f6293 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -4,12 +4,13 @@ use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::* use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue}; use alloy_primitives::{aliases::B32, keccak256, map::HashMap, B64, U256}; use alloy_sol_types::SolValue; -use foundry_common::{ens::namehash, fs}; +use foundry_common::{ens::namehash, fs, TYPE_BINDING_PREFIX}; use foundry_config::fs_permissions::FsAccessKind; use foundry_evm_core::constants::DEFAULT_CREATE2_DEPLOYER; use proptest::prelude::Strategy; use rand::{seq::SliceRandom, Rng, RngCore}; use revm::context::JournalTr; +use std::path::PathBuf; /// Contains locations of traces ignored via cheatcodes. /// @@ -316,25 +317,39 @@ fn random_int(state: &mut Cheatcodes, bits: Option) -> Result { .abi_encode()) } -impl Cheatcode for eip712HashTypeCall { +impl Cheatcode for eip712HashType_0Call { fn apply(&self, state: &mut Cheatcodes) -> Result { - let Self { typeDefinition } = self; + let Self { typeNameOrDefinition } = self; - let type_def = if !typeDefinition.contains('(') { - get_type_def_from_bindings(typeDefinition, state)? + let type_def = if typeNameOrDefinition.contains('(') { + // If the input contains '(', it must be the type definition + EncodeType::parse(typeNameOrDefinition).and_then(|parsed| parsed.canonicalize())? } else { - EncodeType::parse(typeDefinition).and_then(|parsed| parsed.canonicalize())? + // Otherwise, it must be the type name + let path = state + .config + .ensure_path_allowed(&state.config.bind_json_path, FsAccessKind::Read)?; + get_type_def_from_bindings(typeNameOrDefinition, path, &state.config.root)? }; Ok(keccak256(type_def.as_bytes()).to_vec()) } } -fn get_type_def_from_bindings(name: &String, state: &mut Cheatcodes) -> Result { - const TYPE_BINDING_PREFIX: &str = "string constant schema_"; +impl Cheatcode for eip712HashType_1Call { + fn apply(&self, state: &mut Cheatcodes) -> Result { + let Self { bindingsPath, typeName } = self; + + let path = state.config.ensure_path_allowed(bindingsPath, FsAccessKind::Read)?; + let type_def = get_type_def_from_bindings(typeName, path, &state.config.root)?; + + Ok(keccak256(type_def.as_bytes()).to_vec()) + } +} - let path = state.config.root.join("utils").join("JsonBindings.sol"); - let path = state.config.ensure_path_allowed(&path, FsAccessKind::Read)?; +/// Gets the type definition from the bindings in the provided path. Assumes that read validation +/// for the path has already been checked. +fn get_type_def_from_bindings(name: &String, path: PathBuf, root: &PathBuf) -> Result { let content = fs::read_to_string(&path)?; let type_defs: HashMap<&str, &str> = content @@ -353,8 +368,9 @@ fn get_type_def_from_bindings(name: &String, state: &mut Cheatcodes) -> Result>().join("\n"); bail!( - "'{}' not found in 'utils/JsonBindings.sol'.{}", + "'{}' not found in '{}'.{}", name, + path.strip_prefix(root).unwrap_or(&path).to_string_lossy(), if bindings.is_empty() { String::new() } else { diff --git a/crates/common/src/constants.rs b/crates/common/src/constants.rs index b8fcdc7f6fd44..425dad204b1a2 100644 --- a/crates/common/src/constants.rs +++ b/crates/common/src/constants.rs @@ -45,6 +45,9 @@ pub const SYSTEM_TRANSACTION_TYPE: u8 = 126; /// Default user agent set as the header for requests that don't specify one. pub const DEFAULT_USER_AGENT: &str = concat!("foundry/", env!("CARGO_PKG_VERSION")); +/// Prefix for auto-generated type bindings using `forge bind-json`. +pub const TYPE_BINDING_PREFIX: &str = "string constant schema_"; + /// Returns whether the sender is a known L2 system sender that is the first tx in every block. /// /// Transactions from these senders usually don't have a any fee information. diff --git a/crates/forge/src/cmd/bind_json.rs b/crates/forge/src/cmd/bind_json.rs index b82adb50c64dc..ecb76515b16a3 100644 --- a/crates/forge/src/cmd/bind_json.rs +++ b/crates/forge/src/cmd/bind_json.rs @@ -5,7 +5,7 @@ use foundry_cli::{ opts::{solar_pcx_from_solc_project, BuildOpts}, utils::LoadConfig, }; -use foundry_common::fs; +use foundry_common::{fs, TYPE_BINDING_PREFIX}; use foundry_compilers::{ artifacts::{Source, Sources}, multi::{MultiCompilerLanguage, MultiCompilerParsedSource}, @@ -487,8 +487,8 @@ library JsonBindings { for struct_to_write in &self.structs_to_write { writeln!( result, - " string constant schema_{} = \"{}\";", - struct_to_write.name_in_fns, struct_to_write.schema + " {}{} = \"{}\";", + TYPE_BINDING_PREFIX, struct_to_write.name_in_fns, struct_to_write.schema )?; } diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 9a4e0e76d0190..8f9b838003618 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3760,7 +3760,7 @@ string constant CANONICAL = "Transaction(Person from,Person to,Asset tx)Asset(ad contract Eip712Test is DSTest { Vm constant vm = Vm(HEVM_ADDRESS); - function testEip712HashType() public { + function testEip712HashType_byDefinition() public { bytes32 canonicalHash = keccak256(bytes(CANONICAL)); // Can figure out the canonical type from a messy string representation of the type, @@ -3769,25 +3769,63 @@ contract Eip712Test is DSTest { "Person(address wallet, string name) Asset(address token, uint256 amount) Transaction(Person from, Person to, Asset tx)" ); assertEq(fromTypeDef, canonicalHash); + } + + function testEip712HashType_byTypeName() public { + bytes32 canonicalHash = keccak256(bytes(CANONICAL)); // Can figure out the canonical type from the previously generated bindings bytes32 fromTypeName = vm.eip712HashType("Transaction"); assertEq(fromTypeName, canonicalHash); + } + function testReverts_Eip712HashType_invalidName() public { // Reverts if the input type is not found in the bindings vm._expectCheatcodeRevert(); - fromTypeName = vm.eip712HashType("InvalidTypeName"); + bytes32 fromTypeName = vm.eip712HashType("InvalidTypeName"); } } "#, ) .unwrap(); - cmd.forge_fuse().args(["bind-json"]).assert_success(); + // cheatcode by type definition can run without bindings + cmd.forge_fuse() + .args(["test", "--mc", "Eip712Test", "--match-test", "testEip712HashType_byDefinition"]) + .assert_success(); let bindings = prj.root().join("utils").join("JsonBindings.sol"); + prj.update_config(|config| config.fs_permissions.add(PathPermission::read(&bindings))); + + // cheatcode by type name fails if bindings haven't been generated + cmd.forge_fuse() + .args([ + "test", + "--mc", + "Eip712Test", + "--match-test", + "testEip712HashType_byTypeName", + ]) + .assert_failure() + .stdout_eq(str![[r#" +... +Ran 1 test for src/Eip712Cheat.sol:Eip712Test +[FAIL: vm.eip712HashType: failed to read from [..] No such file or directory (os error 2)] testEip712HashType_byTypeName() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in src/Eip712Cheat.sol:Eip712Test +[FAIL: vm.eip712HashType: failed to read from [..] No such file or directory (os error 2)] testEip712HashType_byTypeName() ([GAS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +"#]]); + + cmd.forge_fuse().args(["bind-json"]).assert_success(); assert!(bindings.exists(), "'JsonBindings.sol' was not generated at {bindings:?}"); - prj.update_config(|config| config.fs_permissions.add(PathPermission::read(bindings))); - cmd.forge_fuse().args(["test", "--mc", "Eip712Test", "-vvvv"]).assert_success(); + // with generated bindings, everything works + cmd.forge_fuse().args(["test", "--mc", "Eip712Test"]).assert_success(); }); diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 538ff290733f8..6cbfa37b88d97 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -208,7 +208,8 @@ interface Vm { function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) external pure returns (uint256 privateKey); function difficulty(uint256 newDifficulty) external; function dumpState(string calldata pathToStateJson) external; - function eip712HashType(string memory typeDefinition) external pure returns (bytes32 typeHash); + function eip712HashType(string memory typeNameOrDefinition) external pure returns (bytes32 typeHash); + function eip712HashType(string calldata bindingsPath, string memory typeName) external pure returns (bytes32 typeHash); function ensNamehash(string calldata name) external pure returns (bytes32); function envAddress(string calldata name) external view returns (address value); function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); From cbabab38e9dd1a8f456d251e87f9449a32587160 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 22 May 2025 09:20:54 -0500 Subject: [PATCH 08/21] style: fmt --- crates/forge/tests/cli/eip712.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/forge/tests/cli/eip712.rs b/crates/forge/tests/cli/eip712.rs index dc0bfd4367caa..62aa63079eb4e 100644 --- a/crates/forge/tests/cli/eip712.rs +++ b/crates/forge/tests/cli/eip712.rs @@ -7,31 +7,39 @@ library Structs { struct Foo { Bar bar; } + struct Bar { Art art; } + struct Art { uint256 id; } + struct Complex { Structs2.Foo foo2; Foo[] foos; Rec[][] recs; } + struct Rec { Rec[] rec; } } + library Structs2 { struct Foo { uint256 id; } + struct Rec { Bar[] bar; } + struct Bar { Rec rec; } + struct FooBar { Foo[] foos; Bar[] bars; From 7f64f723b58974e8cb6f09579facf045ea8fc87c Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 22 May 2025 09:45:18 -0500 Subject: [PATCH 09/21] fix: test assertion for win --- crates/forge/tests/cli/test_cmd.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 8f9b838003618..a0760d96f8c03 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3799,25 +3799,19 @@ contract Eip712Test is DSTest { // cheatcode by type name fails if bindings haven't been generated cmd.forge_fuse() - .args([ - "test", - "--mc", - "Eip712Test", - "--match-test", - "testEip712HashType_byTypeName", - ]) + .args(["test", "--mc", "Eip712Test", "--match-test", "testEip712HashType_byTypeName"]) .assert_failure() .stdout_eq(str![[r#" ... Ran 1 test for src/Eip712Cheat.sol:Eip712Test -[FAIL: vm.eip712HashType: failed to read from [..] No such file or directory (os error 2)] testEip712HashType_byTypeName() ([GAS]) +[FAIL: vm.eip712HashType: failed to read from [..] testEip712HashType_byTypeName() ([GAS]) Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) Failing tests: Encountered 1 failing test in src/Eip712Cheat.sol:Eip712Test -[FAIL: vm.eip712HashType: failed to read from [..] No such file or directory (os error 2)] testEip712HashType_byTypeName() ([GAS]) +[FAIL: vm.eip712HashType: failed to read from [..] testEip712HashType_byTypeName() ([GAS]) Encountered a total of 1 failing tests, 0 tests succeeded From 7ff2758621e13353c486cf7a43ea9382bd5895ec Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 22 May 2025 10:00:49 -0500 Subject: [PATCH 10/21] test: custom path --- crates/forge/tests/cli/test_cmd.rs | 65 +++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index a0760d96f8c03..fb7c974d045c7 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3784,6 +3784,14 @@ contract Eip712Test is DSTest { vm._expectCheatcodeRevert(); bytes32 fromTypeName = vm.eip712HashType("InvalidTypeName"); } + + function testEip712HashType_byCustomPathAndTypeName() public { + bytes32 canonicalHash = keccak256(bytes(CANONICAL)); + + // Can figure out the canonical type from the previously generated bindings + bytes32 fromTypeName = vm.eip712HashType("utils/CustomJsonBindings.sol", "Transaction"); + assertEq(fromTypeName, canonicalHash); + } } "#, ) @@ -3820,6 +3828,59 @@ Encountered a total of 1 failing tests, 0 tests succeeded cmd.forge_fuse().args(["bind-json"]).assert_success(); assert!(bindings.exists(), "'JsonBindings.sol' was not generated at {bindings:?}"); - // with generated bindings, everything works - cmd.forge_fuse().args(["test", "--mc", "Eip712Test"]).assert_success(); + // with generated bindings, cheatcode by type name works + cmd.forge_fuse() + .args(["test", "--mc", "Eip712Test", "--match-test", "testEip712HashType_byTypeName"]) + .assert_success(); + + // even with generated bindings, cheatcode by type name fails if name is not present + cmd.forge_fuse() + .args([ + "test", + "--mc", + "Eip712Test", + "--match-test", + "testReverts_Eip712HashType_invalidName", + ]) + .assert_success(); + + let bindings_2 = prj.root().join("utils").join("CustomJsonBindings.sol"); + prj.update_config(|config| { + config.fs_permissions.add(PathPermission::read(&bindings_2)); + config.bind_json.out = bindings_2.clone(); + }); + + // cheatcode by custom path and type name fails if bindings haven't been generated for that path + cmd.forge_fuse() + .args(["test", "--mc", "Eip712Test", "--match-test", "testEip712HashType_byCustomPathAndTypeName"]) + .assert_failure() + .stdout_eq(str![[r#" +... +Ran 1 test for src/Eip712Cheat.sol:Eip712Test +[FAIL: vm.eip712HashType: failed to read from [..] testEip712HashType_byCustomPathAndTypeName() ([GAS]) +Suite result: FAILED. 0 passed; 1 failed; 0 skipped; [ELAPSED] + +Ran 1 test suite [ELAPSED]: 0 tests passed, 1 failed, 0 skipped (1 total tests) + +Failing tests: +Encountered 1 failing test in src/Eip712Cheat.sol:Eip712Test +[FAIL: vm.eip712HashType: failed to read from [..] testEip712HashType_byCustomPathAndTypeName() ([GAS]) + +Encountered a total of 1 failing tests, 0 tests succeeded + +"#]]); + + cmd.forge_fuse().args(["bind-json"]).assert_success(); + assert!(bindings_2.exists(), "'CustomJsonBindings.sol' was not generated at {bindings_2:?}"); + + // with generated bindings, cheatcode by custom path and type name works + cmd.forge_fuse() + .args([ + "test", + "--mc", + "Eip712Test", + "--match-test", + "testEip712HashType_byCustomPathAndTypeName", + ]) + .assert_success(); }); From c0579023d85c96e1160abd6593c1cb9eef40fb82 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 22 May 2025 10:04:32 -0500 Subject: [PATCH 11/21] fix: custom path without being the configured one in `foundry.toml` --- crates/forge/tests/cli/test_cmd.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index fb7c974d045c7..fba03905afd8c 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3847,7 +3847,6 @@ Encountered a total of 1 failing tests, 0 tests succeeded let bindings_2 = prj.root().join("utils").join("CustomJsonBindings.sol"); prj.update_config(|config| { config.fs_permissions.add(PathPermission::read(&bindings_2)); - config.bind_json.out = bindings_2.clone(); }); // cheatcode by custom path and type name fails if bindings haven't been generated for that path @@ -3870,7 +3869,7 @@ Encountered a total of 1 failing tests, 0 tests succeeded "#]]); - cmd.forge_fuse().args(["bind-json"]).assert_success(); + cmd.forge_fuse().args(["bind-json", "utils/CustomJsonBindings.sol"]).assert_success(); assert!(bindings_2.exists(), "'CustomJsonBindings.sol' was not generated at {bindings_2:?}"); // with generated bindings, cheatcode by custom path and type name works From c6f037dc37c322e295eb9ad3c73079a89197307d Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 22 May 2025 10:38:49 -0500 Subject: [PATCH 12/21] fix: use calldata instead of memory in cheatcode fns --- crates/cheatcodes/assets/cheatcodes.json | 4 ++-- crates/cheatcodes/spec/src/vm.rs | 4 ++-- testdata/cheats/Vm.sol | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 7e903135a897a..e00c1f2125891 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -4298,7 +4298,7 @@ "func": { "id": "eip712HashType_0", "description": "Generates the hash of the canonical EIP-712 type representation.\nSupports 2 different inputs:\n 1. Name of the type (i.e. \"Transaction\"):\n * requires previous binding generation with `forge bind-json`.\n * bindings will be retrieved from the path configured in `foundry.toml`.\n 2. String representation of the type (i.e. \"Foo(Bar bar) Bar(uint256 baz)\").\n * Note: the cheatcode will output the canonical type even if the input is malformated\n with the wrong order of elements or with extra whitespaces.", - "declaration": "function eip712HashType(string memory typeNameOrDefinition) external pure returns (bytes32 typeHash);", + "declaration": "function eip712HashType(string calldata typeNameOrDefinition) external pure returns (bytes32 typeHash);", "visibility": "external", "mutability": "pure", "signature": "eip712HashType(string)", @@ -4318,7 +4318,7 @@ "func": { "id": "eip712HashType_1", "description": "Generates the hash of the canonical EIP-712 type representation.\nRequires previous binding generation with `forge bind-json`.\nParams:\n * `bindingsPath`: path where the output of `forge bind-json` is stored.\n * `typeName`: Name of the type (i.e. \"Transaction\").", - "declaration": "function eip712HashType(string calldata bindingsPath, string memory typeName) external pure returns (bytes32 typeHash);", + "declaration": "function eip712HashType(string calldata bindingsPath, string calldata typeName) external pure returns (bytes32 typeHash);", "visibility": "external", "mutability": "pure", "signature": "eip712HashType(string,string)", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 025311768e67c..f9ed82ee4550e 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -2900,7 +2900,7 @@ interface Vm { /// * Note: the cheatcode will output the canonical type even if the input is malformated /// with the wrong order of elements or with extra whitespaces. #[cheatcode(group = Utilities)] - function eip712HashType(string memory typeNameOrDefinition) external pure returns (bytes32 typeHash); + function eip712HashType(string calldata typeNameOrDefinition) external pure returns (bytes32 typeHash); /// Generates the hash of the canonical EIP-712 type representation. /// Requires previous binding generation with `forge bind-json`. @@ -2909,7 +2909,7 @@ interface Vm { /// * `bindingsPath`: path where the output of `forge bind-json` is stored. /// * `typeName`: Name of the type (i.e. "Transaction"). #[cheatcode(group = Utilities)] - function eip712HashType(string calldata bindingsPath, string memory typeName) external pure returns (bytes32 typeHash); + function eip712HashType(string calldata bindingsPath, string calldata typeName) external pure returns (bytes32 typeHash); } } diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 6cbfa37b88d97..ac5928158b647 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -208,8 +208,8 @@ interface Vm { function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) external pure returns (uint256 privateKey); function difficulty(uint256 newDifficulty) external; function dumpState(string calldata pathToStateJson) external; - function eip712HashType(string memory typeNameOrDefinition) external pure returns (bytes32 typeHash); - function eip712HashType(string calldata bindingsPath, string memory typeName) external pure returns (bytes32 typeHash); + function eip712HashType(string calldata typeNameOrDefinition) external pure returns (bytes32 typeHash); + function eip712HashType(string calldata bindingsPath, string calldata typeName) external pure returns (bytes32 typeHash); function ensNamehash(string calldata name) external pure returns (bytes32); function envAddress(string calldata name) external view returns (address value); function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); From 4b23502cb68226ce8650981f4d05d29659299bc9 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <90208954+0xrusowsky@users.noreply.github.com> Date: Thu, 29 May 2025 14:22:21 +0200 Subject: [PATCH 13/21] chore(forge): cheat eip712 struct hash (#10626) --- crates/cheatcodes/assets/cheatcodes.json | 40 +++ crates/cheatcodes/spec/src/vm.rs | 23 ++ crates/cheatcodes/src/utils.rs | 97 ++++++-- crates/forge/tests/cli/test_cmd.rs | 303 +++++++++++++++++++++++ testdata/cheats/Vm.sol | 2 + 5 files changed, 451 insertions(+), 14 deletions(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index e00c1f2125891..1cfbab6382cf5 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -4294,6 +4294,46 @@ "status": "stable", "safety": "unsafe" }, + { + "func": { + "id": "eip712HashStruct_0", + "description": "Generates the struct hash of the canonical EIP-712 type representation and its abi-encoded data.\nSupports 2 different inputs:\n 1. Name of the type (i.e. \"PermitSingle\"):\n * requires previous binding generation with `forge bind-json`.\n * bindings will be retrieved from the path configured in `foundry.toml`.\n 2. String representation of the type (i.e. \"Foo(Bar bar) Bar(uint256 baz)\").\n * Note: the cheatcode will use the canonical type even if the input is malformated\n with the wrong order of elements or with extra whitespaces.", + "declaration": "function eip712HashStruct(string calldata typeNameOrDefinition, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash);", + "visibility": "external", + "mutability": "pure", + "signature": "eip712HashStruct(string,bytes)", + "selector": "0xaedeaebc", + "selectorBytes": [ + 174, + 222, + 174, + 188 + ] + }, + "group": "utilities", + "status": "stable", + "safety": "safe" + }, + { + "func": { + "id": "eip712HashStruct_1", + "description": "Generates the struct hash of the canonical EIP-712 type representation and its abi-encoded data.\nRequires previous binding generation with `forge bind-json`.\nParams:\n * `bindingsPath`: path where the output of `forge bind-json` is stored.\n * `typeName`: Name of the type (i.e. \"PermitSingle\").\n * `abiEncodedData`: ABI-encoded data for the struct that is being hashed.", + "declaration": "function eip712HashStruct(string calldata bindingsPath, string calldata typeName, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash);", + "visibility": "external", + "mutability": "pure", + "signature": "eip712HashStruct(string,string,bytes)", + "selector": "0x6d06c57c", + "selectorBytes": [ + 109, + 6, + 197, + 124 + ] + }, + "group": "utilities", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "eip712HashType_0", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index f9ed82ee4550e..75efabfd53302 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -2910,6 +2910,29 @@ interface Vm { /// * `typeName`: Name of the type (i.e. "Transaction"). #[cheatcode(group = Utilities)] function eip712HashType(string calldata bindingsPath, string calldata typeName) external pure returns (bytes32 typeHash); + + /// Generates the struct hash of the canonical EIP-712 type representation and its abi-encoded data. + /// + /// Supports 2 different inputs: + /// 1. Name of the type (i.e. "PermitSingle"): + /// * requires previous binding generation with `forge bind-json`. + /// * bindings will be retrieved from the path configured in `foundry.toml`. + /// + /// 2. String representation of the type (i.e. "Foo(Bar bar) Bar(uint256 baz)"). + /// * Note: the cheatcode will use the canonical type even if the input is malformated + /// with the wrong order of elements or with extra whitespaces. + #[cheatcode(group = Utilities)] + function eip712HashStruct(string calldata typeNameOrDefinition, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash); + + /// Generates the struct hash of the canonical EIP-712 type representation and its abi-encoded data. + /// Requires previous binding generation with `forge bind-json`. + /// + /// Params: + /// * `bindingsPath`: path where the output of `forge bind-json` is stored. + /// * `typeName`: Name of the type (i.e. "PermitSingle"). + /// * `abiEncodedData`: ABI-encoded data for the struct that is being hashed. + #[cheatcode(group = Utilities)] + function eip712HashStruct(string calldata bindingsPath, string calldata typeName, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash); } } diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 8f0ebb44f6293..8cc78a5d91057 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -1,8 +1,8 @@ //! Implementations of [`Utilities`](spec::Group::Utilities) cheatcodes. use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; -use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue}; -use alloy_primitives::{aliases::B32, keccak256, map::HashMap, B64, U256}; +use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue, Resolver}; +use alloy_primitives::{aliases::B32, keccak256, map::HashMap, Bytes, B64, U256}; use alloy_sol_types::SolValue; use foundry_common::{ens::namehash, fs, TYPE_BINDING_PREFIX}; use foundry_config::fs_permissions::FsAccessKind; @@ -321,16 +321,7 @@ impl Cheatcode for eip712HashType_0Call { fn apply(&self, state: &mut Cheatcodes) -> Result { let Self { typeNameOrDefinition } = self; - let type_def = if typeNameOrDefinition.contains('(') { - // If the input contains '(', it must be the type definition - EncodeType::parse(typeNameOrDefinition).and_then(|parsed| parsed.canonicalize())? - } else { - // Otherwise, it must be the type name - let path = state - .config - .ensure_path_allowed(&state.config.bind_json_path, FsAccessKind::Read)?; - get_type_def_from_bindings(typeNameOrDefinition, path, &state.config.root)? - }; + let type_def = get_canonical_type_def(typeNameOrDefinition, state, None)?; Ok(keccak256(type_def.as_bytes()).to_vec()) } @@ -347,8 +338,49 @@ impl Cheatcode for eip712HashType_1Call { } } -/// Gets the type definition from the bindings in the provided path. Assumes that read validation -/// for the path has already been checked. +impl Cheatcode for eip712HashStruct_0Call { + fn apply(&self, state: &mut Cheatcodes) -> Result { + let Self { typeNameOrDefinition, abiEncodedData } = self; + + let type_def = get_canonical_type_def(typeNameOrDefinition, state, None)?; + let primary = &type_def[..type_def.find('(').unwrap_or(type_def.len())]; + + get_struct_hash(primary, &type_def, abiEncodedData) + } +} + +impl Cheatcode for eip712HashStruct_1Call { + fn apply(&self, state: &mut Cheatcodes) -> Result { + let Self { bindingsPath, typeName, abiEncodedData } = self; + + let path = state.config.ensure_path_allowed(bindingsPath, FsAccessKind::Read)?; + let type_def = get_type_def_from_bindings(typeName, path, &state.config.root)?; + + get_struct_hash(typeName, &type_def, abiEncodedData) + } +} + +fn get_canonical_type_def( + name_or_def: &String, + state: &mut Cheatcodes, + path: Option, +) -> Result { + let type_def = if name_or_def.contains('(') { + // If the input contains '(', it must be the type definition + EncodeType::parse(name_or_def).and_then(|parsed| parsed.canonicalize())? + } else { + // Otherwise, it must be the type name + let path = path.as_ref().unwrap_or(&state.config.bind_json_path); + let path = state.config.ensure_path_allowed(path, FsAccessKind::Read)?; + get_type_def_from_bindings(name_or_def, path, &state.config.root)? + }; + + Ok(type_def) +} + +/// Gets the type definition from the bindings in the provided path. +/// +/// Assumes that read validation for the path has already been checked. fn get_type_def_from_bindings(name: &String, path: PathBuf, root: &PathBuf) -> Result { let content = fs::read_to_string(&path)?; @@ -380,3 +412,40 @@ fn get_type_def_from_bindings(name: &String, path: PathBuf, root: &PathBuf) -> R } } } + +fn get_struct_hash(primary: &str, type_def: &String, abi_encoded_data: &Bytes) -> Result { + let mut resolver = Resolver::default(); + + // Populate the resolver by ingesting the canonical type definition, and then get the + // corresponding `DynSolType` of the primary type. + resolver + .ingest_string(type_def) + .map_err(|e| fmt_err!("Resolver failed to ingest type definition: {e}"))?; + + let resolved_sol_type = resolver + .resolve(primary) + .map_err(|e| fmt_err!("Failed to resolve EIP-712 primary type '{primary}': {e}"))?; + + // ABI-decode the bytes into `DynSolValue::CustomStruct`. + let sol_value = resolved_sol_type.abi_decode(abi_encoded_data.as_ref()).map_err(|e| { + fmt_err!("Failed to ABI decode using resolved_sol_type directly for '{primary}': {e}.") + })?; + + // Use the resolver to properly encode the data. + let encoded_data: Vec = resolver + .encode_data(&sol_value) + .map_err(|e| fmt_err!("Failed to EIP-712 encode data for struct '{primary}': {e}"))? + .ok_or_else(|| fmt_err!("EIP-712 data encoding returned 'None' for struct '{primary}'"))?; + + // Compute the type hash of the primary type. + let type_hash = resolver + .type_hash(primary) + .map_err(|e| fmt_err!("Failed to compute typeHash for EIP712 type '{primary}': {e}"))?; + + // Compute the struct hash of the concatenated type hash and encoded data. + let mut bytes_to_hash = Vec::with_capacity(32 + encoded_data.len()); + bytes_to_hash.extend_from_slice(type_hash.as_slice()); + bytes_to_hash.extend_from_slice(&encoded_data); + + Ok(keccak256(&bytes_to_hash).to_vec()) +} diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index fba03905afd8c..c3c52d117a7c2 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -3883,3 +3883,306 @@ Encountered a total of 1 failing tests, 0 tests succeeded ]) .assert_success(); }); + +forgetest!(test_eip712_hash_struct_simple, |prj, cmd| { + prj.insert_ds_test(); + prj.insert_vm(); + prj.insert_console(); + + prj.add_source( + "Eip712HashStructDomainTest.sol", + r#" +import "./Vm.sol"; +import "./test.sol"; +import "./console.sol"; + +struct EIP712Domain { + string name; + string version; + uint256 chainId; + address verifyingContract; +} + +string constant _EIP712_DOMAIN_TYPE_DEF = "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"; +bytes32 constant _EIP712_DOMAIN_TYPE_HASH = keccak256(bytes(_EIP712_DOMAIN_TYPE_DEF)); + +contract Eip712HashStructDomainTest is DSTest { + Vm constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function testHashEIP712Domain() public { + EIP712Domain memory domain = EIP712Domain({ + name: "Foo", + version: "Bar", + chainId: 1, + verifyingContract: 0xdEADBEeF00000000000000000000000000000000 + }); + + // simulate user-computed domain hash + bytes memory encodedData = abi.encode( + keccak256(bytes(domain.name)), + keccak256(bytes(domain.version)), + bytes32(domain.chainId), + bytes32(uint256(uint160(domain.verifyingContract))) + ); + bytes32 userStructHash = keccak256(abi.encodePacked(_EIP712_DOMAIN_TYPE_HASH, encodedData)); + + // cheatcode-computed domain hash + bytes32 cheatStructHash = vm.eip712HashStruct(_EIP712_DOMAIN_TYPE_DEF, abi.encode(domain)); + console.log("EIP712Domain struct hash from cheatcode:"); + console.logBytes32(cheatStructHash); + + assertEq(cheatStructHash, userStructHash, "EIP712Domain struct hash mismatch"); + } +} +"#, + ) + .unwrap(); + + cmd.forge_fuse().args(["test", "--mc", "Eip712HashStructDomainTest", "-vvvv"]).assert_success(); +}); + +forgetest!(test_eip712_hash_struct_complex, |prj, cmd| { + prj.add_source( + "Eip712Permit.sol", + r#" +struct PermitDetails { + address token; + uint160 amount; + uint48 expiration; + uint48 nonce; +} + +bytes32 constant _PERMIT_DETAILS_TYPEHASH = keccak256( + "PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)" +); + +struct PermitSingle { + PermitDetails details; + address spender; + uint256 sigDeadline; +} + +bytes32 constant _PERMIT_SINGLE_TYPEHASH = keccak256( + "PermitSingle(PermitDetails details,address spender,uint256 sigDeadline)PermitDetails(address token,uint160 amount,uint48 expiration,uint48 nonce)" +); + +// borrowed from https://github.com/Uniswap/permit2/blob/main/src/libraries/PermitHash.sol +library PermitHash { + function hash(PermitSingle memory permitSingle) internal pure returns (bytes32) { + bytes32 permitHash = _hashDetails(permitSingle.details); + return + keccak256(abi.encode(_PERMIT_SINGLE_TYPEHASH, permitHash, permitSingle.spender, permitSingle.sigDeadline)); + } + + function _hashDetails(PermitDetails memory details) internal pure returns (bytes32) { + return keccak256(abi.encode(_PERMIT_DETAILS_TYPEHASH, details)); + } +} +"#, + ) + .unwrap(); + + prj.add_source( + "Eip712Transaction.sol", + r#" +struct Asset { + address token; + uint256 amount; +} + +bytes32 constant _ASSET_TYPEHASH = keccak256( + "Asset(address token,uint256 amount)" +); + +struct Person { + address wallet; + string name; +} + +bytes32 constant _PERSON_TYPEHASH = keccak256( + "Person(address wallet,string name)" +); + +struct Transaction { + Person from; + Person to; + Asset tx; +} + +bytes32 constant _TRANSACTION_TYPEHASH = keccak256( + "Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)" +); + + +library TransactionHash { + function hash(Transaction memory t) internal pure returns (bytes32) { + bytes32 fromHash = _hashPerson(t.from); + bytes32 toHash = _hashPerson(t.to); + bytes32 assetHash = _hashAsset(t.tx); + return + keccak256(abi.encode(_TRANSACTION_TYPEHASH, fromHash, toHash, assetHash)); + } + + function _hashPerson(Person memory person) internal pure returns (bytes32) { + return keccak256( + abi.encode(_PERSON_TYPEHASH, person.wallet, keccak256(bytes(person.name))) + ); + + } + + function _hashAsset(Asset memory asset) internal pure returns (bytes32) { + return keccak256(abi.encode(_ASSET_TYPEHASH, asset)); + } +} + "#, + ) + .unwrap(); + + let bindings = prj.root().join("utils").join("JsonBindings.sol"); + prj.update_config(|config| config.fs_permissions.add(PathPermission::read(&bindings))); + cmd.forge_fuse().args(["bind-json"]).assert_success(); + + prj.insert_ds_test(); + prj.insert_vm(); + prj.insert_console(); + prj.add_source( + "Eip712HashStructTest.sol", + r#" +import "./Vm.sol"; +import "./test.sol"; +import "./console.sol"; +import "./Eip712Permit.sol"; +import "./Eip712Transaction.sol"; + +contract Eip712HashStructTest is DSTest { + Vm constant vm = Vm(HEVM_ADDRESS); + + function testHashPermitSingle_withTypeName() public { + PermitDetails memory details = PermitDetails({ + token: 0x1111111111111111111111111111111111111111, + amount: 1000 ether, + expiration: 12345, + nonce: 1 + }); + + // user-computed permit (using uniswap hash library) + bytes32 userStructHash = PermitHash._hashDetails(details); + + // cheatcode-computed permit + bytes32 cheatStructHash = vm.eip712HashStruct("PermitDetails", abi.encode(details)); + + assertEq(cheatStructHash, userStructHash, "details struct hash mismatch"); + + PermitSingle memory permit = PermitSingle({ + details: details, + spender: 0x2222222222222222222222222222222222222222, + sigDeadline: 12345 + }); + + // user-computed permit (using uniswap hash library) + userStructHash = PermitHash.hash(permit); + + // cheatcode-computed permit + cheatStructHash = vm.eip712HashStruct("PermitSingle", abi.encode(permit)); + console.log("PermitSingle struct hash from cheatcode:"); + console.logBytes32(cheatStructHash); + + assertEq(cheatStructHash, userStructHash, "permit struct hash mismatch"); + } + + function testHashPermitSingle_withTypeDefinion() public { + PermitDetails memory details = PermitDetails({ + token: 0x1111111111111111111111111111111111111111, + amount: 1000 ether, + expiration: 12345, + nonce: 1 + }); + + // user-computed permit (using uniswap hash library) + bytes32 userStructHash = PermitHash._hashDetails(details); + + // cheatcode-computed permit + bytes32 cheatStructHash = vm.eip712HashStruct("PermitDetails(address token, uint160 amount, uint48 expiration, uint48 nonce)", abi.encode(details)); + + assertEq(cheatStructHash, userStructHash, "details struct hash mismatch"); + + PermitSingle memory permit = PermitSingle({ + details: details, + spender: 0x2222222222222222222222222222222222222222, + sigDeadline: 12345 + }); + + // user-computed permit (using uniswap hash library) + userStructHash = PermitHash.hash(permit); + + // cheatcode-computed permit (previously encoding) + cheatStructHash = vm.eip712HashStruct("PermitDetails(address token, uint160 amount, uint48 expiration, uint48 nonce) PermitSingle(PermitDetails details,address spender,uint256 sigDeadline)", abi.encode(permit)); + console.log("PermitSingle struct hash from cheatcode:"); + console.logBytes32(cheatStructHash); + + assertEq(cheatStructHash, userStructHash, "permit struct hash mismatch"); + } + + function testHashTransaction_withTypeName() public { + Asset memory asset = Asset ({ token: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, amount: 100 ether }); + + bytes32 user = TransactionHash._hashAsset(asset); + bytes32 cheat = vm.eip712HashStruct("Asset", abi.encode(asset)); + assertEq(user, cheat, "asset struct hash mismatch"); + + Person memory from = Person ({ wallet: 0x0000000000000000000000000000000000000001, name: "alice" }); + Person memory to = Person ({ wallet: 0x0000000000000000000000000000000000000002, name: "bob" }); + + user = TransactionHash._hashPerson(from); + cheat = vm.eip712HashStruct("Person", abi.encode(from)); + assertEq(user, cheat, "person struct hash mismatch"); + + Transaction memory t = Transaction ({ from: from, to: to, tx: asset }); + + user = TransactionHash.hash(t); + cheat = vm.eip712HashStruct("Transaction", abi.encode(t)); + assertEq(user, cheat, "transaction struct hash mismatch"); + } + + function testHashTransaction_withTypeDefinition() public { + Asset memory asset = Asset ({ token: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, amount: 100 ether }); + + bytes32 user = TransactionHash._hashAsset(asset); + bytes32 cheat = vm.eip712HashStruct("Asset(address token, uint256 amount)", abi.encode(asset)); + assertEq(user, cheat, "asset struct hash mismatch"); + + Person memory from = Person ({ wallet: 0x0000000000000000000000000000000000000001, name: "alice" }); + Person memory to = Person ({ wallet: 0x0000000000000000000000000000000000000002, name: "bob" }); + + user = TransactionHash._hashPerson(from); + cheat = vm.eip712HashStruct("Person(address wallet, string name)", abi.encode(from)); + assertEq(user, cheat, "person struct hash mismatch"); + + Transaction memory t = Transaction ({ from: from, to: to, tx: asset }); + + user = TransactionHash.hash(t); + cheat = vm.eip712HashStruct("Person(address wallet, string name) Asset(address token, uint256 amount) Transaction(Person from, Person to, Asset tx)", abi.encode(t)); + assertEq(user, cheat, "transaction struct hash mismatch"); + } +} +"#, + ) + .unwrap(); + + cmd.forge_fuse() + .args(["test", "--mc", "Eip712HashStructTest", "-vv"]) + .assert_success() + .stdout_eq(str![[r#" +... +[PASS] testHashPermitSingle_withTypeDefinion() ([GAS]) +Logs: + PermitSingle struct hash from cheatcode: + 0x3ed744fdcea02b6b9ad45a9db6e648bf6f18c221909f9ee425191f2a02f9e4a8 + +[PASS] testHashPermitSingle_withTypeName() ([GAS]) +Logs: + PermitSingle struct hash from cheatcode: + 0x3ed744fdcea02b6b9ad45a9db6e648bf6f18c221909f9ee425191f2a02f9e4a8 +... +"#]]); +}); diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index ac5928158b647..9a62a45254576 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -208,6 +208,8 @@ interface Vm { function deriveKey(string calldata mnemonic, string calldata derivationPath, uint32 index, string calldata language) external pure returns (uint256 privateKey); function difficulty(uint256 newDifficulty) external; function dumpState(string calldata pathToStateJson) external; + function eip712HashStruct(string calldata typeNameOrDefinition, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash); + function eip712HashStruct(string calldata bindingsPath, string calldata typeName, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash); function eip712HashType(string calldata typeNameOrDefinition) external pure returns (bytes32 typeHash); function eip712HashType(string calldata bindingsPath, string calldata typeName) external pure returns (bytes32 typeHash); function ensNamehash(string calldata name) external pure returns (bytes32); From 876b7ba9ceaffa4629ef5f27af86fc22dd64c323 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 11:22:24 -0500 Subject: [PATCH 14/21] new cheat: eip712 hash typed data --- crates/cheatcodes/assets/cheatcodes.json | 20 +++++++++++++++ crates/cheatcodes/spec/src/vm.rs | 4 +++ crates/cheatcodes/src/utils.rs | 12 ++++++++- crates/forge/tests/cli/test_cmd.rs | 31 ++++++++++++++++++++++++ testdata/cheats/Vm.sol | 1 + 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/crates/cheatcodes/assets/cheatcodes.json b/crates/cheatcodes/assets/cheatcodes.json index 1cfbab6382cf5..f1d2b617e3a5f 100644 --- a/crates/cheatcodes/assets/cheatcodes.json +++ b/crates/cheatcodes/assets/cheatcodes.json @@ -4374,6 +4374,26 @@ "status": "stable", "safety": "safe" }, + { + "func": { + "id": "eip712HashTypedData", + "description": "Generates a ready-to-sign digest of human-readable typed data following the EIP-712 standard.", + "declaration": "function eip712HashTypedData(string calldata jsonData) external pure returns (bytes32 digest);", + "visibility": "external", + "mutability": "pure", + "signature": "eip712HashTypedData(string)", + "selector": "0xea25e615", + "selectorBytes": [ + 234, + 37, + 230, + 21 + ] + }, + "group": "utilities", + "status": "stable", + "safety": "safe" + }, { "func": { "id": "ensNamehash", diff --git a/crates/cheatcodes/spec/src/vm.rs b/crates/cheatcodes/spec/src/vm.rs index 75efabfd53302..a734c7a033ef1 100644 --- a/crates/cheatcodes/spec/src/vm.rs +++ b/crates/cheatcodes/spec/src/vm.rs @@ -2933,6 +2933,10 @@ interface Vm { /// * `abiEncodedData`: ABI-encoded data for the struct that is being hashed. #[cheatcode(group = Utilities)] function eip712HashStruct(string calldata bindingsPath, string calldata typeName, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash); + + /// Generates a ready-to-sign digest of human-readable typed data following the EIP-712 standard. + #[cheatcode(group = Utilities)] + function eip712HashTypedData(string calldata jsonData) external pure returns (bytes32 digest); } } diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 8cc78a5d91057..dcdbc5497921c 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -1,7 +1,7 @@ //! Implementations of [`Utilities`](spec::Group::Utilities) cheatcodes. use crate::{Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Result, Vm::*}; -use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue, Resolver}; +use alloy_dyn_abi::{eip712_parser::EncodeType, DynSolType, DynSolValue, Resolver, TypedData}; use alloy_primitives::{aliases::B32, keccak256, map::HashMap, Bytes, B64, U256}; use alloy_sol_types::SolValue; use foundry_common::{ens::namehash, fs, TYPE_BINDING_PREFIX}; @@ -360,6 +360,16 @@ impl Cheatcode for eip712HashStruct_1Call { } } +impl Cheatcode for eip712HashTypedDataCall { + fn apply(&self, _state: &mut Cheatcodes) -> Result { + let Self { jsonData } = self; + let typed_data: TypedData = serde_json::from_str(jsonData)?; + let digest = typed_data.eip712_signing_hash()?; + + Ok(digest.to_vec()) + } +} + fn get_canonical_type_def( name_or_def: &String, state: &mut Cheatcodes, diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index c3c52d117a7c2..a36742266251a 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -4186,3 +4186,34 @@ Logs: ... "#]]); }); + +forgetest!(test_eip712_hash_typed_data, |prj, cmd| { + prj.insert_ds_test(); + prj.insert_vm(); + prj.insert_console(); + + prj.add_source( + "Eip712HashTypedData.sol", + r#" +import "./Vm.sol"; +import "./test.sol"; +import "./console.sol"; +contract Eip712HashTypedDataTest is DSTest { + Vm constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); + + function testHashEIP712Message() public { + string memory jsonData = + '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"},{"name":"salt","type":"bytes32"}]},"primaryType":"EIP712Domain","domain":{"name":"example.metamask.io","version":"1","chainId":1,"verifyingContract":"0x0000000000000000000000000000000000000000"},"message":{}}'; + + // since this cheatcode simply exposes an alloy fn, the test has been borrowed from: + // + bytes32 expectedHash = hex"122d1c8ef94b76dad44dcb03fa772361e20855c63311a15d5afe02d1b38f6077"; + assertEq(vm.eip712HashTypedData(jsonData), expectedHash, "EIP712Domain struct hash mismatch"); + } +} +"#, + ) + .unwrap(); + + cmd.forge_fuse().args(["test", "--mc", "Eip712HashTypedDataTest"]).assert_success(); +}); diff --git a/testdata/cheats/Vm.sol b/testdata/cheats/Vm.sol index 9a62a45254576..b439cf9b6f883 100644 --- a/testdata/cheats/Vm.sol +++ b/testdata/cheats/Vm.sol @@ -212,6 +212,7 @@ interface Vm { function eip712HashStruct(string calldata bindingsPath, string calldata typeName, bytes calldata abiEncodedData) external pure returns (bytes32 typeHash); function eip712HashType(string calldata typeNameOrDefinition) external pure returns (bytes32 typeHash); function eip712HashType(string calldata bindingsPath, string calldata typeName) external pure returns (bytes32 typeHash); + function eip712HashTypedData(string calldata jsonData) external pure returns (bytes32 digest); function ensNamehash(string calldata name) external pure returns (bytes32); function envAddress(string calldata name) external view returns (address value); function envAddress(string calldata name, string calldata delim) external view returns (address[] memory value); From f8dddb6b0eae2c8a2f972b3cba34aa8a0451db46 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 12:14:22 -0500 Subject: [PATCH 15/21] bump solar and compilers --- Cargo.lock | 59 ++++++++++++++++++++++++++++++------------------------ Cargo.toml | 13 ++++-------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b63184bd63615..b06a7b9b8542b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4303,9 +4303,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.16.1" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6154e503612a175a88ff342592f0a44664dda54a508d9443121b62b1701f91" +checksum = "fe41ab4be8c70e139241dfa4c8b4f30f905a1c92fa13123255e2eeedc5ffa63d" dependencies = [ "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", @@ -4340,9 +4340,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.16.1" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efca59ffe52914a8ff4ae4e8e97e9fa5d782031d2f5a2d1fb109fa6aac26653d" +checksum = "afd39a92e4cf1ea15b283a8ad2c55af4ec05f5f9334601d62afd1a05abe78e84" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -4350,9 +4350,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.16.1" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a3ffc93f94d2c4ae0ff0f7a12cdeaa5fbb043ced0c558cabd05631e32ac508a" +checksum = "5a3999266fe758acc25725f649d964c7ddf77b38fd00ac9423b74e65901c687d" dependencies = [ "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", @@ -4373,9 +4373,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.16.1" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f077777aa33f933f9f01e90f9ed78e4a40ed60a6380798b528681ca9519a577" +checksum = "b1b7b83ebff9bdb25b35070152169a6ea720d21b7d201debf527b4b11569ea62" dependencies = [ "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", @@ -4388,9 +4388,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.16.1" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff92d5831075077fe64391dcbbe4a1518bce0439f97ab6a940fa1b9c1f3eaa2" +checksum = "80f3bb9ac0bc9f509b3ed080092b4c0e8fa1ff58243d89454e96fa0cc4599d1e" dependencies = [ "alloy-primitives 1.1.2", "cfg-if", @@ -8598,8 +8598,9 @@ dependencies = [ [[package]] name = "solar-ast" -version = "0.1.3" -source = "git+https://github.com/paradigmxyz/solar.git?branch=dani%2Fresolver-absolute-paths#97e8dd947e20b5530edbad1422393ef9ca5678d2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acb0d9abd88c1325e5c0f9bb153ebfb02ed40bc9639067d0ad120f5d29ee8777" dependencies = [ "alloy-primitives 1.1.2", "bumpalo", @@ -8616,16 +8617,18 @@ dependencies = [ [[package]] name = "solar-config" -version = "0.1.3" -source = "git+https://github.com/paradigmxyz/solar.git?branch=dani%2Fresolver-absolute-paths#97e8dd947e20b5530edbad1422393ef9ca5678d2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "908d455bb7c04acd783bd157b63791bf010cf6a495a845e48f7aee334aad319f" dependencies = [ "strum 0.27.1", ] [[package]] name = "solar-data-structures" -version = "0.1.3" -source = "git+https://github.com/paradigmxyz/solar.git?branch=dani%2Fresolver-absolute-paths#97e8dd947e20b5530edbad1422393ef9ca5678d2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8b5a697cab81241c4623b4546c69e57182202847a75d7c0047c0dd10b923d8c" dependencies = [ "bumpalo", "index_vec", @@ -8638,8 +8641,9 @@ dependencies = [ [[package]] name = "solar-interface" -version = "0.1.3" -source = "git+https://github.com/paradigmxyz/solar.git?branch=dani%2Fresolver-absolute-paths#97e8dd947e20b5530edbad1422393ef9ca5678d2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33e49e5a714ec80d7f9c8942584e5e86add1c5e824aa175d0681e9ac7a10e5cc" dependencies = [ "annotate-snippets", "anstream", @@ -8648,7 +8652,7 @@ dependencies = [ "derive_builder", "derive_more 2.0.1", "dunce", - "itertools 0.10.5", + "itertools 0.14.0", "itoa", "lasso", "match_cfg", @@ -8665,8 +8669,9 @@ dependencies = [ [[package]] name = "solar-macros" -version = "0.1.3" -source = "git+https://github.com/paradigmxyz/solar.git?branch=dani%2Fresolver-absolute-paths#97e8dd947e20b5530edbad1422393ef9ca5678d2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17f8b99f28f358b41acb6efe4d7b8f326541b3c58a15dd1931d6fe581feefef" dependencies = [ "proc-macro2", "quote", @@ -8675,13 +8680,14 @@ dependencies = [ [[package]] name = "solar-parse" -version = "0.1.3" -source = "git+https://github.com/paradigmxyz/solar.git?branch=dani%2Fresolver-absolute-paths#97e8dd947e20b5530edbad1422393ef9ca5678d2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6982ef2ecfb1338c774c743ab7166ce8c3dcc92089ab77fad58eeb632b201e9" dependencies = [ "alloy-primitives 1.1.2", "bitflags 2.9.1", "bumpalo", - "itertools 0.10.5", + "itertools 0.14.0", "memchr", "num-bigint", "num-rational", @@ -8695,8 +8701,9 @@ dependencies = [ [[package]] name = "solar-sema" -version = "0.1.3" -source = "git+https://github.com/paradigmxyz/solar.git?branch=dani%2Fresolver-absolute-paths#97e8dd947e20b5530edbad1422393ef9ca5678d2" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8e0a3a6dfc7f4987bfb93f9b56079150407ef55c459964a1541c669554b74d" dependencies = [ "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", diff --git a/Cargo.toml b/Cargo.toml index 615f85eadfeb8..fdefa17aad45f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -197,12 +197,12 @@ foundry-linking = { path = "crates/linking" } # solc & compilation utilities foundry-block-explorers = { version = "0.17.0", default-features = false } -foundry-compilers = { version = "0.16.1", default-features = false } +foundry-compilers = { version = "0.16.4", default-features = false } foundry-fork-db = "0.14" solang-parser = { version = "=0.3.8", package = "foundry-solang-parser" } -solar-parse = { version = "=0.1.3", default-features = false } -solar-sema = { version = "=0.1.3", default-features = false } -solar-interface = { version = "=0.1.3", default-features = false } +solar-parse = { version = "=0.1.4", default-features = false } +solar-sema = { version = "=0.1.4", default-features = false } +solar-interface = { version = "=0.1.4", default-features = false } ## alloy alloy-consensus = { version = "1.0.5", default-features = false } @@ -392,10 +392,5 @@ revm = { git = "https://github.com/bluealloy/revm.git", rev = "b5808253" } op-revm = { git = "https://github.com/bluealloy/revm.git", rev = "b5808253" } # revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors.git", rev = "a625c04" } -## solar -solar-parse = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/resolver-absolute-paths" } -solar-sema = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/resolver-absolute-paths" } -solar-interface = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/resolver-absolute-paths" } - ## foundry # foundry-fork-db = { git = "https://github.com/foundry-rs/foundry-fork-db", rev = "811a61a" } From 2c0780894f9dd5babb1a0cef1814fec3a8d39dc4 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 12:31:59 -0500 Subject: [PATCH 16/21] fix: failing compiler test --- crates/forge/tests/cli/compiler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/forge/tests/cli/compiler.rs b/crates/forge/tests/cli/compiler.rs index 0b58221f2a1d0..ae07aec6d0225 100644 --- a/crates/forge/tests/cli/compiler.rs +++ b/crates/forge/tests/cli/compiler.rs @@ -242,7 +242,7 @@ Solidity: Vyper: -0.4.0 (<= cancun): +0.4.0 (<= prague): ├── src/Counter.vy └── src/ICounter.vyi From cac75c3618c4c033ba43a29b40a2a5c9422da86f Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 13:40:43 -0500 Subject: [PATCH 17/21] bump compiler and explorers + patch vyper prague -> cancun --- Cargo.lock | 438 +++++++++++++++-------------- Cargo.toml | 4 +- crates/forge/src/cmd/compiler.rs | 6 + crates/forge/tests/cli/compiler.rs | 2 +- 4 files changed, 240 insertions(+), 210 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b06a7b9b8542b..ffb91c44d1464 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-chains" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5848366a4f08dca1caca0a6151294a4799fe2e59ba25df100491d92e0b921b1c" +checksum = "517e5acbd38b6d4c59da380e8bbadc6d365bf001903ce46cf5521c53c647e07b" dependencies = [ "alloy-primitives 1.1.2", "num_enum", @@ -70,14 +70,14 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9835a7b6216cb8118323581e58a18b1a5014fce55ce718635aaea7fa07bd700" +checksum = "ad451f9a70c341d951bca4e811d74dbe1e193897acd17e9dbac1353698cc430b" dependencies = [ - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-primitives 1.1.2", "alloy-rlp", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-trie", "auto_impl", "c-kzg", @@ -94,23 +94,23 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aec7fdaa4f0e4e1ca7e9271ca7887fdd467ca3b9e101582dc6c2bbd1645eae1c" +checksum = "142daffb15d5be1a2b20d2cd540edbcef03037b55d4ff69dc06beb4d06286dba" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-primitives 1.1.2", "alloy-rlp", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "serde", ] [[package]] name = "alloy-contract" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e810f27a4162190b50cdf4dabedee3ad9028772bd7e370fdfc0f63b8bc116d3" +checksum = "ebf25443920ecb9728cb087fe4dc04a0b290bd6ac85638c58fe94aba70f1a44e" dependencies = [ "alloy-consensus", "alloy-dyn-abi 1.1.2", @@ -224,16 +224,16 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fc566136b705991072f8f79762525e14f0ca39c38d45b034944770cb6c6b67" +checksum = "3056872f6da48046913e76edb5ddced272861f6032f09461aea1a2497be5ae5d" dependencies = [ "alloy-eip2124", "alloy-eip2930", "alloy-eip7702", "alloy-primitives 1.1.2", "alloy-rlp", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "auto_impl", "c-kzg", "derive_more 2.0.1", @@ -249,7 +249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0210f2d5854895b376f7fbbf78f3e33eb4f0e59abc503502cc0ed8d295a837" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-hardforks", "alloy-primitives 1.1.2", "alloy-sol-types 1.1.2", @@ -263,22 +263,22 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c0124a3174f136171df8498e4700266774c9de1008a0b987766cf215d08f6" +checksum = "c98fb40f07997529235cc474de814cd7bd9de561e101716289095696c0e4639d" dependencies = [ - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-primitives 1.1.2", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-trie", "serde", ] [[package]] name = "alloy-hardforks" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b40cc82a2283e3ce6317bc1f0134ea50d20e8c1965393045ee952fb28a65ddbd" +checksum = "fbff8445282ec080c2673692062bd4930d7a0d6bda257caf138cfc650c503000" dependencies = [ "alloy-chains", "alloy-eip2124", @@ -313,9 +313,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1590f44abdfe98686827a4e083b711ad17f843bf6ed8a50b78d3242f12a00ada" +checksum = "dc08b31ebf9273839bd9a01f9333cbb7a3abb4e820c312ade349dd18bdc79581" dependencies = [ "alloy-primitives 1.1.2", "alloy-sol-types 1.1.2", @@ -327,19 +327,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049a9022caa0c0a2dcd2bc2ea23fa098508f4a81d5dda774d753570a41e6acdb" +checksum = "ed117b08f0cc190312bf0c38c34cf4f0dabfb4ea8f330071c587cd7160a88cb2" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-json-rpc", "alloy-network-primitives", "alloy-primitives 1.1.2", "alloy-rpc-types-any", "alloy-rpc-types-eth", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-signer", "alloy-sol-types 1.1.2", "async-trait", @@ -353,14 +353,14 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5630ce8552579d1393383b27fe4bfe7c700fb7480189a82fc054da24521947aa" +checksum = "c7162ff7be8649c0c391f4e248d1273e85c62076703a1f3ec7daf76b283d886d" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-primitives 1.1.2", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "serde", ] @@ -371,7 +371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ee0165cc5f92d8866c0a21320ee6f089a7e1d0cebbf7008c37a6380a912ebe2" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-evm", "alloy-op-hardforks", "alloy-primitives 1.1.2", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "alloy-op-hardforks" -version = "0.2.2" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a79617217008626a24fb52b02d532bf4554ac9b184a2d22bd6c5df628c151601" +checksum = "9ddfbb5cc9f614efa5d56e0d7226214bb67b29271d44b6ddfcbbe25eb0ff898b" dependencies = [ "alloy-hardforks", "auto_impl", @@ -451,13 +451,13 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "959aedfc417737e2a59961c95e92c59726386748d85ef516a0d0687b440d3184" +checksum = "d84eba1fd8b6fe8b02f2acd5dd7033d0f179e304bd722d11e817db570d1fa6c4" dependencies = [ "alloy-chains", "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-json-rpc", "alloy-network", "alloy-network-primitives", @@ -496,9 +496,9 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf694cd1494284e73e23b62568bb5df6777f99eaec6c0a4705ac5a5c61707208" +checksum = "8550f7306e0230fc835eb2ff4af0a96362db4b6fc3f25767d161e0ad0ac765bf" dependencies = [ "alloy-json-rpc", "alloy-primitives 1.1.2", @@ -539,9 +539,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20436220214938c4fe223244f00fbd618dda80572b8ffe7839d382a6c54f1c" +checksum = "518a699422a3eab800f3dac2130d8f2edba8e4fff267b27a9c7dc6a2b0d313ee" dependencies = [ "alloy-json-rpc", "alloy-primitives 1.1.2", @@ -567,9 +567,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2981f41486264b2e254bc51b2691bbef9ed87d0545d11f31cb26af3109cc4" +checksum = "c000cab4ec26a4b3e29d144e999e1c539c2fa0abed871bf90311eb3466187ca8" dependencies = [ "alloy-primitives 1.1.2", "alloy-rpc-types-anvil", @@ -577,38 +577,38 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "serde", ] [[package]] name = "alloy-rpc-types-anvil" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebe3dcbc6c85678f29c205b2fcf6b110b32287bf6b72bbee37ed9011404e926" +checksum = "8abecc34549a208b5f91bc7f02df3205c36e2aa6586f1d9375c3382da1066b3b" dependencies = [ "alloy-primitives 1.1.2", "alloy-rpc-types-eth", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "serde", ] [[package]] name = "alloy-rpc-types-any" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c583654aab419fe9e553ba86ab503e1cda0b855509ac95210c4ca6df84724255" +checksum = "508b2fbe66d952089aa694e53802327798806498cd29ff88c75135770ecaabfc" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", ] [[package]] name = "alloy-rpc-types-debug" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7913c67b874db23446a4cdd020da1bbc828513bd83536ccabfca403b71cdeaf9" +checksum = "8c832f2e851801093928dbb4b7bd83cd22270faf76b2e080646b806a285c8757" dependencies = [ "alloy-primitives 1.1.2", "serde", @@ -616,15 +616,15 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b70151dc3282ce4bbde31b80a7f0f1e53b9dec9b187f528394e8f0a0411975" +checksum = "cab52691970553d84879d777419fa7b6a2e92e9fe8641f9324cc071008c2f656" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-primitives 1.1.2", "alloy-rlp", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "derive_more 2.0.1", "jsonwebtoken", "rand 0.8.5", @@ -634,17 +634,17 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4496ab5f898c88e9153b88fcb6738e2d58b2ba6d7d85c3144ee83c990316a3" +checksum = "fcaf7dff0fdd756a714d58014f4f8354a1706ebf9fa2cf73431e0aeec3c9431e" dependencies = [ "alloy-consensus", "alloy-consensus-any", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-network-primitives", "alloy-primitives 1.1.2", "alloy-rlp", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-sol-types 1.1.2", "itertools 0.14.0", "serde", @@ -654,13 +654,13 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf555fe777cf7d11b8ebe837aca0b0ceb74f1ed9937f938b8c9fbd1460994cf" +checksum = "6e3507a04e868dd83219ad3cd6a8c58aefccb64d33f426b3934423a206343e84" dependencies = [ "alloy-primitives 1.1.2", "alloy-rpc-types-eth", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "serde", "serde_json", "thiserror 2.0.12", @@ -668,13 +668,13 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87c69ea401ce851b52c9b07d838173cd3c23c11a552a5e5ddde3ffd834647a46" +checksum = "eec36272621c3ac82b47dd77f0508346687730b1c2e3e10d3715705c217c0a05" dependencies = [ "alloy-primitives 1.1.2", "alloy-rpc-types-eth", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "serde", ] @@ -691,9 +691,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c34ffc38f543bfdceed8c1fa5253fa5131455bb3654976be4cc3a4ae6d61f4" +checksum = "730e8f2edf2fc224cabd1c25d090e1655fa6137b2e409f92e5eec735903f1507" dependencies = [ "alloy-primitives 1.1.2", "serde", @@ -702,9 +702,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59245704a5dbd20b93913f4a20aa41b45c4c134f82e119bb54de4b627e003955" +checksum = "6b0d2428445ec13edc711909e023d7779618504c4800be055a5b940025dbafe3" dependencies = [ "alloy-dyn-abi 1.1.2", "alloy-primitives 1.1.2", @@ -719,9 +719,9 @@ dependencies = [ [[package]] name = "alloy-signer-aws" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a24ea892abc29582dce6df5a1266ddf620fe93a04eb0265a3072c68c8b0ea10" +checksum = "6be3d371299b62eac5aa459fa58e8d1c761aabdc637573ae258ab744457fcc88" dependencies = [ "alloy-consensus", "alloy-network", @@ -737,9 +737,9 @@ dependencies = [ [[package]] name = "alloy-signer-gcp" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07be333cf6b3f06475d86b5fe39e5f94285714fffaf961173ff87448180f346" +checksum = "df298e47bbb7d0a8e06b603046b91062c11ba70d22f8a6c9bab1c1468bd856d0" dependencies = [ "alloy-consensus", "alloy-network", @@ -755,9 +755,9 @@ dependencies = [ [[package]] name = "alloy-signer-ledger" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ad29d22519ce6fcf85edb8fb0d335216e8522c4458cdd92792f06c2173f9f2" +checksum = "3b0e049299cc7e131a438a904f89a493bcea45cd92bbed3e50116a28bc27987c" dependencies = [ "alloy-consensus", "alloy-dyn-abi 1.1.2", @@ -775,9 +775,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae78644ab0945e95efa2dc0cfac8f53aa1226fe85c294a0d8ad82c5cc9f09a2" +checksum = "e14fe6fedb7fe6e0dfae47fe020684f1d8e063274ef14bca387ddb7a6efa8ec1" dependencies = [ "alloy-consensus", "alloy-network", @@ -794,9 +794,9 @@ dependencies = [ [[package]] name = "alloy-signer-trezor" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a384f096c65ec6f9c541dd8a0d1217f38ff7aa0d2565254d03d9a51c23b5c6" +checksum = "26c7df3624131eeecf74c18e5cd59bcc125633bad407b1938161edf89eb71485" dependencies = [ "alloy-consensus", "alloy-network", @@ -955,9 +955,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56afd0561a291e84de9d5616fa3def4c4925a09117ea3b08d4d5d207c4f7083" +checksum = "a712bdfeff42401a7dd9518f72f617574c36226a9b5414537fedc34350b73bf9" dependencies = [ "alloy-json-rpc", "alloy-primitives 1.1.2", @@ -978,9 +978,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90770711e649bb3df0a8a666ae7b80d1d77eff5462eaf6bb4d3eaf134f6e636e" +checksum = "7ea5a76d7f2572174a382aedf36875bedf60bcc41116c9f031cf08040703a2dc" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -993,9 +993,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983693379572a06e2bc1050116d975395604b357e1f2ac4420dd385d9ee18c11" +checksum = "606af17a7e064d219746f6d2625676122c79d78bf73dfe746d6db9ecd7dbcb85" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -1013,9 +1013,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "1.0.5" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90569cc2e13f5cdf53f42d5b3347cf4a89fccbcf9978cf08b165b4a1c6447672" +checksum = "e0c6f9b37cd8d44aab959613966cc9d4d7a9b429c575cec43b3e5b46ea109a79" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -1147,12 +1147,12 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa" dependencies = [ "anstyle", - "once_cell", + "once_cell_polyfill", "windows-sys 0.59.0", ] @@ -1164,7 +1164,7 @@ dependencies = [ "alloy-consensus", "alloy-contract", "alloy-dyn-abi 1.1.2", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-evm", "alloy-genesis", "alloy-network", @@ -1174,7 +1174,7 @@ dependencies = [ "alloy-pubsub", "alloy-rlp", "alloy-rpc-types", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-signer", "alloy-signer-local", "alloy-sol-types 1.1.2", @@ -1226,12 +1226,12 @@ version = "1.2.0" dependencies = [ "alloy-consensus", "alloy-dyn-abi 1.1.2", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-network", "alloy-primitives 1.1.2", "alloy-rlp", "alloy-rpc-types", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "bytes", "foundry-common", "foundry-evm", @@ -1812,14 +1812,14 @@ dependencies = [ "percent-encoding", "pin-project-lite", "tracing", - "uuid 1.16.0", + "uuid 1.17.0", ] [[package]] name = "aws-sdk-kms" -version = "1.69.0" +version = "1.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64c93b24f98760979113386e444886fc812632d4d84910b802d69a2bdbb5349" +checksum = "0eef6a94141a43ee28404bf135828ad9bdd4936bfa2a84ad8dea355c94646a35" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1839,9 +1839,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.68.0" +version = "1.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd5f01ea61fed99b5fe4877abff6c56943342a56ff145e9e0c7e2494419008be" +checksum = "95a4fd09d6e863655d99cd2260f271c6d1030dc6bfad68e19e126d2e4c8ceb18" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1861,9 +1861,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.69.0" +version = "1.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27454e4c55aaa4ef65647e3a1cf095cb834ca6d54e959e2909f1fef96ad87860" +checksum = "3224ab02ebb3074467a33d57caf6fcb487ca36f3697fdd381b0428dc72380696" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1883,9 +1883,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.69.0" +version = "1.72.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffd6ef5d00c94215960fabcdf2d9fe7c090eed8be482d66d47b92d4aba1dd4aa" +checksum = "f6933f189ed1255e78175fbd73fb200c0aae7240d220ed3346f567b0ddca3083" dependencies = [ "aws-credential-types", "aws-runtime", @@ -2469,7 +2469,7 @@ dependencies = [ "alloy-provider", "alloy-rlp", "alloy-rpc-types", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-signer", "alloy-signer-local", "alloy-sol-types 1.1.2", @@ -2522,9 +2522,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.23" +version = "1.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" +checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7" dependencies = [ "jobserver", "libc", @@ -2649,9 +2649,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.38" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed93b9805f8ba930df42c2590f05453d5ec36cbb85d018868a5b24d31f6ac000" +checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" dependencies = [ "clap_builder", "clap_derive", @@ -2659,9 +2659,9 @@ dependencies = [ [[package]] name = "clap-verbosity-flag" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2678fade3b77aa3a8ff3aae87e9c008d3fb00473a41c71fbf74e91c8c7b37e84" +checksum = "eeab6a5cdfc795a05538422012f20a5496f050223c91be4e5420bfd13c641fb1" dependencies = [ "clap", "log", @@ -2669,9 +2669,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.38" +version = "4.5.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379026ff283facf611b0ea629334361c4211d1b12ee01024eec1591133b04120" +checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" dependencies = [ "anstream", "anstyle", @@ -2684,9 +2684,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.50" +version = "4.5.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91d3baa3bcd889d60e6ef28874126a0b384fd225ab83aa6d8a801c519194ce1" +checksum = "8d2267df7f3c8e74e38268887ea5235d4dfadd39bfff2d56ab82d61776be355e" dependencies = [ "clap", ] @@ -2994,9 +2994,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ "core-foundation-sys", "libc", @@ -3868,7 +3868,7 @@ dependencies = [ "alloy-primitives 1.1.2", "alloy-provider", "alloy-rpc-types", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-signer", "alloy-signer-local", "alloy-transport", @@ -3907,7 +3907,7 @@ dependencies = [ "inferno", "itertools 0.14.0", "mockall", - "opener", + "opener 0.7.2", "parking_lot", "paste", "path-slash", @@ -3987,13 +3987,13 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-dyn-abi 1.1.2", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-json-abi 1.1.2", "alloy-network", "alloy-primitives 1.1.2", "alloy-provider", "alloy-rpc-types", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-signer", "clap", "dialoguer", @@ -4101,9 +4101,9 @@ dependencies = [ [[package]] name = "foundry-block-explorers" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6129df264d2bd245ade4ed21a92f605bfd592dca8fb8e6e1adde1b9bd4288681" +checksum = "7dd57f39a860475780c0b001167b2bb9039e78d8d09323c6949897f5351ffae6" dependencies = [ "alloy-chains", "alloy-json-abi 1.1.2", @@ -4184,7 +4184,7 @@ version = "1.2.0" dependencies = [ "alloy-chains", "alloy-dyn-abi 1.1.2", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", "alloy-provider", @@ -4232,7 +4232,7 @@ dependencies = [ "alloy-consensus", "alloy-contract", "alloy-dyn-abi 1.1.2", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-json-abi 1.1.2", "alloy-json-rpc", "alloy-network", @@ -4241,7 +4241,7 @@ dependencies = [ "alloy-pubsub", "alloy-rpc-client", "alloy-rpc-types", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "alloy-sol-types 1.1.2", "alloy-transport", "alloy-transport-http", @@ -4291,7 +4291,7 @@ dependencies = [ "alloy-network", "alloy-primitives 1.1.2", "alloy-rpc-types", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "chrono", "foundry-macros", "revm", @@ -4303,9 +4303,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.16.4" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe41ab4be8c70e139241dfa4c8b4f30f905a1c92fa13123255e2eeedc5ffa63d" +checksum = "6e3e990fb891b4f7caa49271c842d8eaece61431106b33c52f9d511dc7270eee" dependencies = [ "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", @@ -4340,9 +4340,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts" -version = "0.16.4" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afd39a92e4cf1ea15b283a8ad2c55af4ec05f5f9334601d62afd1a05abe78e84" +checksum = "8234ce9c22e8e5047dcae2acd10cb0ccd448dd5058d4e341310bb9dabcec4aa6" dependencies = [ "foundry-compilers-artifacts-solc", "foundry-compilers-artifacts-vyper", @@ -4350,9 +4350,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-solc" -version = "0.16.4" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3999266fe758acc25725f649d964c7ddf77b38fd00ac9423b74e65901c687d" +checksum = "2d46c321c7a688810301c8efa1d020ee876b6bcf4a327c6a50bf807845b94c41" dependencies = [ "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", @@ -4373,9 +4373,9 @@ dependencies = [ [[package]] name = "foundry-compilers-artifacts-vyper" -version = "0.16.4" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1b7b83ebff9bdb25b35070152169a6ea720d21b7d201debf527b4b11569ea62" +checksum = "2f2e6f66303fe27dbd3123db706f9f25bae1b46ddcb97191e0f5ac199db94403" dependencies = [ "alloy-json-abi 1.1.2", "alloy-primitives 1.1.2", @@ -4388,9 +4388,9 @@ dependencies = [ [[package]] name = "foundry-compilers-core" -version = "0.16.4" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f3bb9ac0bc9f509b3ed080092b4c0e8fa1ff58243d89454e96fa0cc4599d1e" +checksum = "34dd4424b0bcbbf6ad9e6f80377136b84edcfcbb4234a0c59afa78a89d5a9ee8" dependencies = [ "alloy-primitives 1.1.2", "cfg-if", @@ -5235,11 +5235,10 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.5" +version = "0.27.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +checksum = "03a01595e11bdcec50946522c32dde3fc6914743000a68b93000965f2f02406d" dependencies = [ - "futures-util", "http 1.3.1", "hyper", "hyper-util", @@ -5249,7 +5248,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 0.26.11", + "webpki-roots 1.0.0", ] [[package]] @@ -5267,22 +5266,28 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" dependencies = [ + "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.3.1", "http-body 1.0.1", "hyper", + "ipnet", "libc", + "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -5521,6 +5526,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is-terminal" version = "0.4.16" @@ -5582,9 +5597,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806" +checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" dependencies = [ "jiff-static", "jiff-tzdb-platform", @@ -5597,9 +5612,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48" +checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" dependencies = [ "proc-macro2", "quote", @@ -5723,9 +5738,9 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7047a26de42016abf8f181b46b398aef0b77ad46711df41847f6ed869a2a1d5b" +checksum = "ba4ebbd48ce411c1d10fb35185f5a51a7bfa3d8b24b4e330d30c9e3a34129501" dependencies = [ "ascii-canvas", "bit-set", @@ -5744,9 +5759,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.22.1" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d05b3fe34b8bd562c338db725dfa9beb9451a48f65f129ccb9538b48d2c93b" +checksum = "b5baa5e9ff84f1aefd264e6869907646538a52147a755d494517a8007fb48733" dependencies = [ "regex-automata 0.4.9", "rustversion", @@ -5792,9 +5807,9 @@ dependencies = [ [[package]] name = "libloading" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", "windows-targets 0.53.0", @@ -6042,9 +6057,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "mdbook" -version = "0.4.49" +version = "0.4.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1daacee059634081dee4250d2814763a365b92dfe14bfdef964bc27835209d4" +checksum = "a87e65420ab45ca9c1b8cdf698f95b710cc826d373fa550f0f7fad82beac9328" dependencies = [ "ammonia", "anyhow", @@ -6057,8 +6072,7 @@ dependencies = [ "hex", "log", "memchr", - "once_cell", - "opener", + "opener 0.8.2", "pulldown-cmark", "regex", "serde", @@ -6160,14 +6174,14 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -6204,11 +6218,11 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "newtype-uuid" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3224f0e8be7c2a1ebc77ef9c3eecb90f55c6594399ee825de964526b3c9056" +checksum = "a8ba303c7a8f8fdee1fe1513cfd918f50f1c69bf65c91b39217bfc2b2af5c081" dependencies = [ - "uuid 1.16.0", + "uuid 1.17.0", ] [[package]] @@ -6502,6 +6516,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "once_map" version = "0.4.21" @@ -6521,10 +6541,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f318b09e24148f07392c5e011bae047a0043851f9041145df5f3b01e4fedd1e" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-primitives 1.1.2", "alloy-rlp", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "derive_more 2.0.1", "serde", "thiserror 2.0.12", @@ -6537,11 +6557,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15ede8322c10c21249de4fced204e2af4978972e715afee34b6fe684d73880cf" dependencies = [ "alloy-consensus", - "alloy-eips 1.0.5", + "alloy-eips 1.0.9", "alloy-network-primitives", "alloy-primitives 1.1.2", "alloy-rpc-types-eth", - "alloy-serde 1.0.5", + "alloy-serde 1.0.9", "derive_more 2.0.1", "op-alloy-consensus", "serde", @@ -6578,6 +6598,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "opener" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771b9704f8cd8b424ec747a320b30b47517a6966ba2c7da90047c16f4a962223" +dependencies = [ + "bstr", + "normpath", + "windows-sys 0.59.0", +] + [[package]] name = "openssl-probe" version = "0.1.6" @@ -6622,9 +6653,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.7.4" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fde3d0718baf5bc92f577d652001da0f8d54cd03a7974e118d04fc888dc23d" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" dependencies = [ "arrayvec", "bitvec", @@ -6638,9 +6669,9 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.7.4" +version = "3.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581c837bb6b9541ce7faa9377c20616e4fb7650f6b0f68bc93c827ee504fb7b3" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -7220,7 +7251,7 @@ dependencies = [ "quick-xml 0.37.5", "strip-ansi-escapes", "thiserror 2.0.12", - "uuid 1.16.0", + "uuid 1.17.0", ] [[package]] @@ -7517,9 +7548,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.12.15" +version = "0.12.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +checksum = "e98ff6b0dbbe4d5a37318f433d4fc82babd21631f194d370409ceb2e40b2f0b5" dependencies = [ "async-compression", "base64 0.22.1", @@ -7546,26 +7577,24 @@ dependencies = [ "quinn", "rustls", "rustls-native-certs", - "rustls-pemfile", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", "tokio-rustls", "tokio-socks", "tokio-util", "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.11", - "windows-registry", + "webpki-roots 1.0.0", ] [[package]] @@ -7834,9 +7863,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a46eb779843b2c4f21fac5773e25d6d5b7c8f0922876c91541790d2ca27eef" +checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" dependencies = [ "alloy-rlp", "arbitrary", @@ -7975,15 +8004,6 @@ dependencies = [ "security-framework", ] -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "rustls-pki-types" version = "1.12.0" @@ -8008,9 +8028,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" [[package]] name = "rusty-fork" @@ -8192,7 +8212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ "bitflags 2.9.1", - "core-foundation 0.10.0", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -8588,9 +8608,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" dependencies = [ "libc", "windows-sys 0.52.0", @@ -8772,7 +8792,7 @@ dependencies = [ "thiserror 2.0.12", "tokio", "toml_edit", - "uuid 1.16.0", + "uuid 1.17.0", "zip", "zip-extract", ] @@ -9298,9 +9318,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.45.0" +version = "1.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" dependencies = [ "backtrace", "bytes", @@ -9509,12 +9529,14 @@ dependencies = [ "http-body-util", "http-range-header", "httpdate", + "iri-string", "mime", "mime_guess", "percent-encoding", "pin-project-lite", "tokio", "tokio-util", + "tower", "tower-layer", "tower-service", "tracing", @@ -9893,12 +9915,14 @@ dependencies = [ [[package]] name = "uuid" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" dependencies = [ "getrandom 0.3.3", + "js-sys", "serde", + "wasm-bindgen", ] [[package]] @@ -10313,15 +10337,15 @@ dependencies = [ [[package]] name = "windows-core" -version = "0.61.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46ec44dc15085cea82cf9c78f85a9114c463a369786585ad2882d1ff0b0acf40" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ "windows-implement", "windows-interface", "windows-link", "windows-result", - "windows-strings 0.4.1", + "windows-strings 0.4.2", ] [[package]] @@ -10386,9 +10410,9 @@ dependencies = [ [[package]] name = "windows-result" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b895b5356fc36103d0f64dd1e94dfa7ac5633f1c9dd6e80fe9ec4adef69e09d" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" dependencies = [ "windows-link", ] @@ -10404,9 +10428,9 @@ dependencies = [ [[package]] name = "windows-strings" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a7ab927b2637c19b3dbe0965e75d8f2d30bdd697a1516191cad2ec4df8fb28a" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" dependencies = [ "windows-link", ] diff --git a/Cargo.toml b/Cargo.toml index fdefa17aad45f..6e5bafa630107 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -196,8 +196,8 @@ foundry-wallets = { path = "crates/wallets" } foundry-linking = { path = "crates/linking" } # solc & compilation utilities -foundry-block-explorers = { version = "0.17.0", default-features = false } -foundry-compilers = { version = "0.16.4", default-features = false } +foundry-block-explorers = { version = "0.18.0", default-features = false } +foundry-compilers = { version = "0.17.0", default-features = false } foundry-fork-db = "0.14" solang-parser = { version = "=0.3.8", package = "foundry-solang-parser" } solar-parse = { version = "=0.1.4", default-features = false } diff --git a/crates/forge/src/cmd/compiler.rs b/crates/forge/src/cmd/compiler.rs index 19e4354ca9cb4..50aebf969f252 100644 --- a/crates/forge/src/cmd/compiler.rs +++ b/crates/forge/src/cmd/compiler.rs @@ -139,6 +139,12 @@ impl ResolveArgs { 0 => sh_println!("- {version}")?, _ => { if let Some(evm) = &resolved_compiler.evm_version { + if let Some(path) = &resolved_compiler.paths.last() { + if path.ends_with(".vy") && evm == &EvmVersion::Prague { + sh_println!("{version} (<= {evm}):", evm = EvmVersion::Cancun)?; + continue; + } + }; sh_println!("{version} (<= {evm}):")? } else { sh_println!("{version}:")? diff --git a/crates/forge/tests/cli/compiler.rs b/crates/forge/tests/cli/compiler.rs index ae07aec6d0225..0b58221f2a1d0 100644 --- a/crates/forge/tests/cli/compiler.rs +++ b/crates/forge/tests/cli/compiler.rs @@ -242,7 +242,7 @@ Solidity: Vyper: -0.4.0 (<= prague): +0.4.0 (<= cancun): ├── src/Counter.vy └── src/ICounter.vyi From b998d0e2b97a3d7afab38edc62444c944d745710 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 13:54:47 -0500 Subject: [PATCH 18/21] style: clippy --- crates/anvil/core/src/eth/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index bca300cac6cd8..be38aa4ad45e3 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -35,6 +35,7 @@ pub struct Params { /// Represents ethereum JSON-RPC API #[derive(Clone, Debug, serde::Deserialize)] #[serde(tag = "method", content = "params")] +#[allow(clippy::large_enum_variant)] pub enum EthRequest { #[serde(rename = "web3_clientVersion", with = "empty_params")] Web3ClientVersion(()), @@ -640,7 +641,7 @@ pub enum EthRequest { /// Add an address to the [`DelegationCapability`] of the wallet /// - /// [`DelegationCapability`]: wallet::DelegationCapability + /// [`DelegationCapability`]: wallet::DelegationCapability #[serde(rename = "anvil_addCapability", with = "sequence")] AnvilAddCapability(Address), From 452cbcea15d83ec84de3dc1378829955afa2f69a Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 14:48:13 -0500 Subject: [PATCH 19/21] fix: check for `.vyi` paths --- crates/forge/src/cmd/compiler.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/forge/src/cmd/compiler.rs b/crates/forge/src/cmd/compiler.rs index 50aebf969f252..d631f3ea3fd44 100644 --- a/crates/forge/src/cmd/compiler.rs +++ b/crates/forge/src/cmd/compiler.rs @@ -140,7 +140,9 @@ impl ResolveArgs { _ => { if let Some(evm) = &resolved_compiler.evm_version { if let Some(path) = &resolved_compiler.paths.last() { - if path.ends_with(".vy") && evm == &EvmVersion::Prague { + if (path.ends_with(".vy") || path.ends_with(".vyi")) && + evm == &EvmVersion::Prague + { sh_println!("{version} (<= {evm}):", evm = EvmVersion::Cancun)?; continue; } From ce7948f29ffdec807448a7956c39058cd6da2496 Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 15:17:28 -0500 Subject: [PATCH 20/21] style: simplify --- crates/forge/src/cmd/compiler.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/forge/src/cmd/compiler.rs b/crates/forge/src/cmd/compiler.rs index d631f3ea3fd44..b8612ec58a801 100644 --- a/crates/forge/src/cmd/compiler.rs +++ b/crates/forge/src/cmd/compiler.rs @@ -139,17 +139,19 @@ impl ResolveArgs { 0 => sh_println!("- {version}")?, _ => { if let Some(evm) = &resolved_compiler.evm_version { - if let Some(path) = &resolved_compiler.paths.last() { - if (path.ends_with(".vy") || path.ends_with(".vyi")) && - evm == &EvmVersion::Prague - { - sh_println!("{version} (<= {evm}):", evm = EvmVersion::Cancun)?; - continue; - } - }; - sh_println!("{version} (<= {evm}):")? + // Vyper does not yet support Prague, so we normalize it to Cancun. + if evm == &EvmVersion::Prague && + resolved_compiler + .paths + .last() + .is_some_and(|p| p.ends_with(".vy") || p.ends_with(".vyi")) + { + sh_println!("{version} (<= {evm}):", evm = EvmVersion::Cancun)?; + } else { + sh_println!("{version} (<= {evm}):")?; + } } else { - sh_println!("{version}:")? + sh_println!("{version}:")?; } } } From d35f49897829a0e6620e6c7600cfe38dc7ffcc7b Mon Sep 17 00:00:00 2001 From: 0xrusowsky <0xrusowsky@proton.me> Date: Thu, 29 May 2025 15:17:41 -0500 Subject: [PATCH 21/21] style: simplify --- crates/forge/src/cmd/compiler.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/forge/src/cmd/compiler.rs b/crates/forge/src/cmd/compiler.rs index b8612ec58a801..27e7aabcf972d 100644 --- a/crates/forge/src/cmd/compiler.rs +++ b/crates/forge/src/cmd/compiler.rs @@ -146,12 +146,12 @@ impl ResolveArgs { .last() .is_some_and(|p| p.ends_with(".vy") || p.ends_with(".vyi")) { - sh_println!("{version} (<= {evm}):", evm = EvmVersion::Cancun)?; + sh_println!("{version} (<= {evm}):", evm = EvmVersion::Cancun)? } else { - sh_println!("{version} (<= {evm}):")?; + sh_println!("{version} (<= {evm}):")? } } else { - sh_println!("{version}:")?; + sh_println!("{version}:")? } } }