diff --git a/Cargo.lock b/Cargo.lock index c59308fcae617..0b0ad430bba5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,6 +75,49 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-primitives" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e416903084d3392ebd32d94735c395d6709415b76c7728e594d3f996f2b03e65" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more", + "getrandom 0.2.10", + "hex-literal", + "itoa", + "proptest", + "ruint", + "serde", + "tiny-keccak", +] + +[[package]] +name = "alloy-rlp" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f938f00332d63a5b0ac687bd6f46d03884638948921d9f8b50c59563d421ae25" +dependencies = [ + "alloy-rlp-derive", + "arrayvec", + "bytes", + "smol_str", +] + +[[package]] +name = "alloy-rlp-derive" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa5bb468bc7c46e0c5074d418f575262ff79451242e5ac1380121ed4e23c4fd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.33", +] + [[package]] name = "ammonia" version = "3.3.0" @@ -125,9 +168,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" +checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" [[package]] name = "anstyle-parse" @@ -161,6 +204,7 @@ dependencies = [ name = "anvil" version = "0.2.0" dependencies = [ + "alloy-primitives", "anvil-core", "anvil-rpc", "anvil-server", @@ -208,6 +252,7 @@ dependencies = [ name = "anvil-core" version = "0.2.0" dependencies = [ + "alloy-primitives", "bytes", "ethers-core", "foundry-evm", @@ -310,7 +355,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -321,7 +366,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -625,9 +670,9 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592" +checksum = "fb9ac64500cc83ce4b9f8dafa78186aa008c8dea77a09b94cd307fd0cd5022a8" dependencies = [ "camino", "cargo-platform", @@ -797,9 +842,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.2" +version = "4.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +checksum = "84ed82781cea27b43c9b106a979fe450a13a31aab0500595fb3fc06616de08e6" dependencies = [ "clap_builder", "clap_derive", @@ -848,7 +893,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -1576,7 +1621,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -1715,7 +1760,7 @@ dependencies = [ [[package]] name = "ethers" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "ethers-addressbook", "ethers-contract", @@ -1730,7 +1775,7 @@ dependencies = [ [[package]] name = "ethers-addressbook" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "ethers-core", "once_cell", @@ -1741,7 +1786,7 @@ dependencies = [ [[package]] name = "ethers-contract" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "const-hex", "ethers-contract-abigen", @@ -1759,7 +1804,7 @@ dependencies = [ [[package]] name = "ethers-contract-abigen" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "Inflector", "const-hex", @@ -1774,7 +1819,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.32", + "syn 2.0.33", "toml 0.7.8", "walkdir", ] @@ -1782,7 +1827,7 @@ dependencies = [ [[package]] name = "ethers-contract-derive" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "Inflector", "const-hex", @@ -1791,13 +1836,13 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] name = "ethers-core" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "arrayvec", "bytes", @@ -1816,7 +1861,7 @@ dependencies = [ "serde", "serde_json", "strum 0.25.0", - "syn 2.0.32", + "syn 2.0.33", "tempfile", "thiserror", "tiny-keccak", @@ -1826,7 +1871,7 @@ dependencies = [ [[package]] name = "ethers-etherscan" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "ethers-core", "ethers-solc", @@ -1841,7 +1886,7 @@ dependencies = [ [[package]] name = "ethers-middleware" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "async-trait", "auto_impl", @@ -1867,7 +1912,7 @@ dependencies = [ [[package]] name = "ethers-providers" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "async-trait", "auto_impl", @@ -1905,7 +1950,7 @@ dependencies = [ [[package]] name = "ethers-signers" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "async-trait", "coins-bip32", @@ -1932,7 +1977,7 @@ dependencies = [ [[package]] name = "ethers-solc" version = "2.0.10" -source = "git+https://github.com/gakonst/ethers-rs#a28c5ae9b76d04a8b4ab39e5afcd772bfd43bd1f" +source = "git+https://github.com/gakonst/ethers-rs#90b87bd85be98caa8bb592b67f3f9acbc8a409cf" dependencies = [ "cfg-if", "const-hex", @@ -2019,7 +2064,7 @@ dependencies = [ "bytes", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -2133,6 +2178,7 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" name = "forge" version = "0.2.0" dependencies = [ + "alloy-primitives", "anvil", "async-trait", "bytes", @@ -2246,7 +2292,7 @@ dependencies = [ "ethers-providers", "eyre", "foundry-macros", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -2382,6 +2428,7 @@ dependencies = [ name = "foundry-evm" version = "0.2.0" dependencies = [ + "alloy-primitives", "auto_impl", "bytes", "const-hex", @@ -2429,7 +2476,7 @@ version = "0.2.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -2580,7 +2627,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -3638,9 +3685,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libgit2-sys" @@ -3887,7 +3934,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4154,7 +4201,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4258,7 +4305,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4459,7 +4506,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4508,7 +4555,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4611,7 +4658,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4649,7 +4696,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4743,7 +4790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -4796,9 +4843,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -4811,7 +4858,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", "version_check", "yansi 1.0.0-rc.1", ] @@ -5159,10 +5206,9 @@ dependencies = [ [[package]] name = "revm" version = "3.3.0" -source = "git+https://github.com/bluealloy/revm/?rev=429da731cd8efdc0939ed912240b2667b9155834#429da731cd8efdc0939ed912240b2667b9155834" +source = "git+https://github.com/Evalir/revm/?branch=reintroduce-alloy-rebased#5845079baf8df56f624a1ecae579a05f8423a2df" dependencies = [ "auto_impl", - "rayon", "revm-interpreter", "revm-precompile", "serde", @@ -5172,19 +5218,18 @@ dependencies = [ [[package]] name = "revm-interpreter" version = "1.1.2" -source = "git+https://github.com/bluealloy/revm/?rev=429da731cd8efdc0939ed912240b2667b9155834#429da731cd8efdc0939ed912240b2667b9155834" +source = "git+https://github.com/Evalir/revm/?branch=reintroduce-alloy-rebased#5845079baf8df56f624a1ecae579a05f8423a2df" dependencies = [ "derive_more", "enumn", "revm-primitives", "serde", - "sha3", ] [[package]] name = "revm-precompile" version = "2.0.3" -source = "git+https://github.com/bluealloy/revm/?rev=429da731cd8efdc0939ed912240b2667b9155834#429da731cd8efdc0939ed912240b2667b9155834" +source = "git+https://github.com/Evalir/revm/?branch=reintroduce-alloy-rebased#5845079baf8df56f624a1ecae579a05f8423a2df" dependencies = [ "k256", "num", @@ -5192,30 +5237,27 @@ dependencies = [ "revm-primitives", "ripemd", "sha2 0.10.7", - "sha3", "substrate-bn", ] [[package]] name = "revm-primitives" version = "1.1.2" -source = "git+https://github.com/bluealloy/revm/?rev=429da731cd8efdc0939ed912240b2667b9155834#429da731cd8efdc0939ed912240b2667b9155834" +source = "git+https://github.com/Evalir/revm/?branch=reintroduce-alloy-rebased#5845079baf8df56f624a1ecae579a05f8423a2df" dependencies = [ + "alloy-primitives", + "alloy-rlp", "auto_impl", "bitflags 2.4.0", "bitvec", "bytes", "derive_more", "enumn", - "fixed-hash", "hashbrown 0.14.0", "hex", "hex-literal", "primitive-types", - "rlp", - "ruint", "serde", - "sha3", ] [[package]] @@ -5301,10 +5343,9 @@ version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95294d6e3a6192f3aabf91c38f56505a625aa495533442744185a36d75a790c4" dependencies = [ - "primitive-types", + "alloy-rlp", "proptest", "rand 0.8.5", - "rlp", "ruint-macro", "serde", "valuable", @@ -5478,7 +5519,7 @@ checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", - "rustls-webpki 0.101.4", + "rustls-webpki 0.101.5", "sct", ] @@ -5505,9 +5546,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.100.2" +version = "0.100.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" +checksum = "5f6a5fc258f1c1276dfe3016516945546e2d5383911efc0fc4f1cdc5df3a4ae3" dependencies = [ "ring", "untrusted", @@ -5515,9 +5556,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.4" +version = "0.101.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +checksum = "45a27e3b59326c16e23d30aeb7a36a24cc0d29e71d68ff611cdfb4a01d013bed" dependencies = [ "ring", "untrusted", @@ -5741,7 +5782,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -5809,7 +5850,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -5983,6 +6024,15 @@ version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +[[package]] +name = "smol_str" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +dependencies = [ + "serde", +] + [[package]] name = "socket2" version = "0.4.9" @@ -5995,9 +6045,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", "windows-sys 0.48.0", @@ -6115,7 +6165,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -6183,9 +6233,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.32" +version = "2.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2" +checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668" dependencies = [ "proc-macro2", "quote", @@ -6300,7 +6350,7 @@ checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -6411,7 +6461,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.3", + "socket2 0.5.4", "tokio-macros", "windows-sys 0.48.0", ] @@ -6424,7 +6474,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -6661,7 +6711,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", ] [[package]] @@ -6897,9 +6947,9 @@ checksum = "98e90c70c9f0d4d1ee6d0a7d04aa06cb9bbd53d8cfbdd62a0269a7c2eb640552" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -7088,7 +7138,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", "wasm-bindgen-shared", ] @@ -7122,7 +7172,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.32", + "syn 2.0.33", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -7207,7 +7257,7 @@ version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" dependencies = [ - "rustls-webpki 0.100.2", + "rustls-webpki 0.100.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 04dc284000d39..c853f7a5ad455 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -155,6 +155,8 @@ itertools = "0.11" solang-parser = "=0.3.2" tikv-jemallocator = "0.5.4" +alloy-primitives = { version = "0.3", default-features = false } + #[patch."https://github.com/gakonst/ethers-rs"] #ethers = { path = "../ethers-rs/ethers" } #ethers-addressbook = { path = "../ethers-rs/ethers-addressbook" } @@ -168,7 +170,7 @@ tikv-jemallocator = "0.5.4" #ethers-solc = { path = "../ethers-rs/ethers-solc" } [patch.crates-io] -revm = { git = "https://github.com/bluealloy/revm/", rev = "429da731cd8efdc0939ed912240b2667b9155834" } -revm-interpreter = { git = "https://github.com/bluealloy/revm/", rev = "429da731cd8efdc0939ed912240b2667b9155834" } -revm-precompile = { git = "https://github.com/bluealloy/revm/", rev = "429da731cd8efdc0939ed912240b2667b9155834" } -revm-primitives = { git = "https://github.com/bluealloy/revm/", rev = "429da731cd8efdc0939ed912240b2667b9155834" } +revm = { git = "https://github.com/Evalir/revm/", branch = "reintroduce-alloy-rebased" } +revm-interpreter = { git = "https://github.com/Evalir/revm/", branch = "reintroduce-alloy-rebased" } +revm-precompile = { git = "https://github.com/Evalir/revm/", branch = "reintroduce-alloy-rebased" } +revm-primitives = { git = "https://github.com/Evalir/revm/", branch = "reintroduce-alloy-rebased" } diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 9d7a24ba379ba..058123836405f 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -34,6 +34,7 @@ ethers = { workspace = true, features = ["rustls", "ws", "ipc"] } trie-db = { version = "0.23" } hash-db = { version = "0.15" } memory-db = { version = "0.29" } +alloy-primitives = { workspace = true, default-features = false, features = ["std", "serde"] } # axum related axum = { version = "0.5", features = ["ws"] } diff --git a/crates/anvil/core/Cargo.toml b/crates/anvil/core/Cargo.toml index 9c371cb851353..3b49e4bc5819e 100644 --- a/crates/anvil/core/Cargo.toml +++ b/crates/anvil/core/Cargo.toml @@ -14,6 +14,8 @@ repository.workspace = true foundry-evm = { path = "../../evm" } revm = { workspace = true, default-features = false, features = ["std", "serde", "memory_limit"] } + +alloy-primitives = { workspace = true, default-features = false, features = ["std", "serde"] } ethers-core.workspace = true serde = { version = "1", features = ["derive"], optional = true } serde_json = "1" diff --git a/crates/anvil/core/src/eth/proof.rs b/crates/anvil/core/src/eth/proof.rs index a1a2f3b5a3c24..a0714ab29e2df 100644 --- a/crates/anvil/core/src/eth/proof.rs +++ b/crates/anvil/core/src/eth/proof.rs @@ -5,6 +5,7 @@ use ethers_core::{ types::{H256, U256}, utils::rlp, }; +use foundry_evm::utils::b256_to_h256; use revm::primitives::KECCAK_EMPTY; // reexport for convenience pub use ethers_core::types::{EIP1186ProofResponse as AccountProof, StorageProof}; @@ -28,7 +29,7 @@ impl Default for BasicAccount { BasicAccount { balance: 0.into(), nonce: 0.into(), - code_hash: KECCAK_EMPTY.into(), + code_hash: b256_to_h256(KECCAK_EMPTY), storage_root: KECCAK_NULL_RLP, } } diff --git a/crates/anvil/core/src/eth/receipt.rs b/crates/anvil/core/src/eth/receipt.rs index e663b33329086..5b3a15eee0690 100644 --- a/crates/anvil/core/src/eth/receipt.rs +++ b/crates/anvil/core/src/eth/receipt.rs @@ -6,7 +6,7 @@ use ethers_core::{ rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}, }, }; -use foundry_evm::utils::{b256_to_h256, h256_to_b256}; +use foundry_evm::utils::{b160_to_h160, b256_to_h256, h160_to_b160, h256_to_b256}; #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "fastrlp", derive(open_fastrlp::RlpEncodable, open_fastrlp::RlpDecodable))] @@ -21,9 +21,9 @@ impl From for Log { fn from(log: revm::primitives::Log) -> Self { let revm::primitives::Log { address, topics, data } = log; Log { - address: address.into(), + address: b160_to_h160(address), topics: topics.into_iter().map(b256_to_h256).collect(), - data: data.into(), + data: ethers_core::types::Bytes(data.0), } } } @@ -32,9 +32,9 @@ impl From for revm::primitives::Log { fn from(log: Log) -> Self { let Log { address, topics, data } = log; revm::primitives::Log { - address: address.into(), + address: h160_to_b160(address), topics: topics.into_iter().map(h256_to_b256).collect(), - data: data.0, + data: alloy_primitives::Bytes(data.0), } } } diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index 8445f7dfd663c..ae3fd15983d07 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -14,7 +14,10 @@ use ethers_core::{ rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}, }, }; -use foundry_evm::trace::CallTraceArena; +use foundry_evm::{ + trace::CallTraceArena, + utils::{h160_to_b160, u256_to_ru256}, +}; use revm::{ interpreter::InstructionResult, primitives::{CreateScheme, TransactTo, TxEnv}, @@ -1185,7 +1188,7 @@ impl PendingTransaction { pub fn to_revm_tx_env(&self) -> TxEnv { fn transact_to(kind: &TransactionKind) -> TransactTo { match kind { - TransactionKind::Call(c) => TransactTo::Call((*c).into()), + TransactionKind::Call(c) => TransactTo::Call(h160_to_b160(*c)), TransactionKind::Create => TransactTo::Create(CreateScheme::Create), } } @@ -1196,13 +1199,13 @@ impl PendingTransaction { let chain_id = tx.chain_id(); let LegacyTransaction { nonce, gas_price, gas_limit, value, kind, input, .. } = tx; TxEnv { - caller: caller.into(), + caller: h160_to_b160(caller), transact_to: transact_to(kind), - data: input.0.clone(), + data: alloy_primitives::Bytes(input.0.clone()), chain_id, nonce: Some(nonce.as_u64()), - value: (*value).into(), - gas_price: (*gas_price).into(), + value: u256_to_ru256(*value), + gas_price: u256_to_ru256(*gas_price), gas_priority_fee: None, gas_limit: gas_limit.as_u64(), access_list: vec![], @@ -1221,13 +1224,13 @@ impl PendingTransaction { .. } = tx; TxEnv { - caller: caller.into(), + caller: h160_to_b160(caller), transact_to: transact_to(kind), - data: input.0.clone(), + data: alloy_primitives::Bytes(input.0.clone()), chain_id: Some(*chain_id), nonce: Some(nonce.as_u64()), - value: (*value).into(), - gas_price: (*gas_price).into(), + value: u256_to_ru256(*value), + gas_price: u256_to_ru256(*gas_price), gas_priority_fee: None, gas_limit: gas_limit.as_u64(), access_list: to_revm_access_list(access_list.0.clone()), @@ -1247,14 +1250,14 @@ impl PendingTransaction { .. } = tx; TxEnv { - caller: caller.into(), + caller: h160_to_b160(caller), transact_to: transact_to(kind), - data: input.0.clone(), + data: alloy_primitives::Bytes(input.0.clone()), chain_id: Some(*chain_id), nonce: Some(nonce.as_u64()), - value: (*value).into(), - gas_price: (*max_fee_per_gas).into(), - gas_priority_fee: Some((*max_priority_fee_per_gas).into()), + value: u256_to_ru256(*value), + gas_price: u256_to_ru256(*max_fee_per_gas), + gas_priority_fee: Some(u256_to_ru256(*max_priority_fee_per_gas)), gas_limit: gas_limit.as_u64(), access_list: to_revm_access_list(access_list.0.clone()), } diff --git a/crates/anvil/core/src/eth/utils.rs b/crates/anvil/core/src/eth/utils.rs index f6a0f6f412b28..7ee856195cd1f 100644 --- a/crates/anvil/core/src/eth/utils.rs +++ b/crates/anvil/core/src/eth/utils.rs @@ -1,3 +1,4 @@ +use alloy_primitives::{Address as rAddress, U256 as rU256}; use ethers_core::{ types::{transaction::eip2930::AccessListItem, Address, U256}, utils::{ @@ -6,7 +7,6 @@ use ethers_core::{ }, }; use foundry_evm::utils::{h160_to_b160, h256_to_u256_be, u256_to_ru256}; -use revm::primitives::{B160, U256 as rU256}; pub fn enveloped(id: u8, v: &T, s: &mut RlpStream) { let encoded = rlp::encode(v); @@ -22,7 +22,7 @@ pub fn to_access_list(list: Vec) -> Vec<(Address, Vec)> { .collect() } -pub fn to_revm_access_list(list: Vec) -> Vec<(B160, Vec)> { +pub fn to_revm_access_list(list: Vec) -> Vec<(rAddress, Vec)> { list.into_iter() .map(|item| { ( diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index e9e4a7ae2866b..1f33c17890743 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -38,7 +38,9 @@ use foundry_evm::{ }, revm, revm::primitives::{BlockEnv, CfgEnv, SpecId, TxEnv, U256 as rU256}, - utils::{apply_chain_and_block_specific_env_changes, h256_to_b256, u256_to_ru256}, + utils::{ + apply_chain_and_block_specific_env_changes, b160_to_h160, h256_to_b256, u256_to_ru256, + }, }; use parking_lot::RwLock; use serde_json::{json, to_writer, Value}; @@ -795,8 +797,8 @@ impl NodeConfig { let mut env = revm::primitives::Env { cfg, block: BlockEnv { - gas_limit: self.gas_limit.into(), - basefee: self.get_base_fee().into(), + gas_limit: u256_to_ru256(self.gas_limit), + basefee: u256_to_ru256(self.get_base_fee()), ..Default::default() }, tx: TxEnv { chain_id: self.get_chain_id().into(), ..Default::default() }, @@ -884,8 +886,8 @@ latest block number: {latest_block}" env.block = BlockEnv { number: rU256::from(fork_block_number), - timestamp: block.timestamp.into(), - difficulty: block.difficulty.into(), + timestamp: u256_to_ru256(block.timestamp), + difficulty: u256_to_ru256(block.difficulty), // ensures prevrandao is set prevrandao: Some(block.mix_hash.unwrap_or_default()).map(h256_to_b256), gas_limit, @@ -992,7 +994,7 @@ latest block number: {latest_block}" let genesis = GenesisConfig { timestamp: self.get_genesis_timestamp(), - balance: self.genesis_balance.into(), + balance: u256_to_ru256(self.genesis_balance), accounts: self.genesis_accounts.iter().map(|acc| acc.address()).collect(), fork_genesis_account_infos: Arc::new(Default::default()), genesis_init: self.genesis.clone(), @@ -1016,7 +1018,7 @@ latest block number: {latest_block}" // if the option is not disabled and we are not forking. if !self.disable_default_create2_deployer && self.eth_rpc_url.is_none() { backend - .set_create2_deployer(DEFAULT_CREATE2_DEPLOYER) + .set_create2_deployer(b160_to_h160(DEFAULT_CREATE2_DEPLOYER)) .await .expect("Failed to create default create2 deployer"); } diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index c0046ce2064a0..5c2d107b1ce39 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -64,6 +64,7 @@ use foundry_evm::{ interpreter::{return_ok, return_revert, InstructionResult}, primitives::BlockEnv, }, + utils::ru256_to_u256, }; use futures::channel::mpsc::Receiver; use parking_lot::RwLock; @@ -2062,7 +2063,7 @@ impl EthApi { // get the highest possible gas limit, either the request's set value or the currently // configured gas limit - let mut highest_gas_limit = request.gas.unwrap_or(block_env.gas_limit.into()); + let mut highest_gas_limit = request.gas.unwrap_or(ru256_to_u256(block_env.gas_limit)); // check with the funds of the sender if let Some(from) = request.from { diff --git a/crates/anvil/src/eth/backend/db.rs b/crates/anvil/src/eth/backend/db.rs index 6967b79d13f8c..d64b7247bf426 100644 --- a/crates/anvil/src/eth/backend/db.rs +++ b/crates/anvil/src/eth/backend/db.rs @@ -1,6 +1,7 @@ //! Helper types for working with [revm](foundry_evm::revm) use crate::{mem::state::trie_hash_db, revm::primitives::AccountInfo, U256}; +use alloy_primitives::{Address as B160, B256, U256 as rU256}; use anvil_core::eth::trie::KeccakHasher; use ethers::{ prelude::{Address, Bytes}, @@ -15,9 +16,10 @@ use foundry_evm::{ }, revm::{ db::{CacheDB, DbAccount}, - primitives::{Bytecode, B160, B256, KECCAK_EMPTY, U256 as rU256}, + primitives::{Bytecode, KECCAK_EMPTY}, Database, DatabaseCommit, }, + utils::{h160_to_b160, h256_to_b256, u256_to_ru256}, HashMap, }; use hash_db::HashDB; @@ -84,7 +86,7 @@ pub trait Db: /// Sets the nonce of the given address fn set_nonce(&mut self, address: Address, nonce: u64) -> DatabaseResult<()> { - let mut info = self.basic(address.into())?.unwrap_or_default(); + let mut info = self.basic(h160_to_b160(address))?.unwrap_or_default(); info.nonce = nonce; self.insert_account(address, info); Ok(()) @@ -92,22 +94,22 @@ pub trait Db: /// Sets the balance of the given address fn set_balance(&mut self, address: Address, balance: U256) -> DatabaseResult<()> { - let mut info = self.basic(address.into())?.unwrap_or_default(); - info.balance = balance.into(); + let mut info = self.basic(h160_to_b160(address))?.unwrap_or_default(); + info.balance = u256_to_ru256(balance); self.insert_account(address, info); Ok(()) } /// Sets the balance of the given address fn set_code(&mut self, address: Address, code: Bytes) -> DatabaseResult<()> { - let mut info = self.basic(address.into())?.unwrap_or_default(); + let mut info = self.basic(h160_to_b160(address))?.unwrap_or_default(); let code_hash = if code.as_ref().is_empty() { KECCAK_EMPTY } else { B256::from_slice(&keccak256(code.as_ref())[..]) }; info.code_hash = code_hash; - info.code = Some(Bytecode::new_raw(code.0).to_checked()); + info.code = Some(Bytecode::new_raw(alloy_primitives::Bytes(code.0)).to_checked()); self.insert_account(address, info); Ok(()) } @@ -124,7 +126,7 @@ pub trait Db: /// Deserialize and add all chain data to the backend storage fn load_state(&mut self, state: SerializableState) -> DatabaseResult { for (addr, account) in state.accounts.into_iter() { - let old_account_nonce = DatabaseRef::basic(self, addr.into()) + let old_account_nonce = DatabaseRef::basic(self, h160_to_b160(addr)) .ok() .and_then(|acc| acc.map(|acc| acc.nonce)) .unwrap_or_default(); @@ -135,12 +137,14 @@ pub trait Db: self.insert_account( addr, AccountInfo { - balance: account.balance.into(), + balance: u256_to_ru256(account.balance), code_hash: KECCAK_EMPTY, // will be set automatically code: if account.code.0.is_empty() { None } else { - Some(Bytecode::new_raw(account.code.0).to_checked()) + Some( + Bytecode::new_raw(alloy_primitives::Bytes(account.code.0)).to_checked(), + ) }, nonce, }, @@ -176,15 +180,15 @@ pub trait Db: /// [Backend::pending_block()](crate::eth::backend::mem::Backend::pending_block()) impl + Send + Sync + Clone + fmt::Debug> Db for CacheDB { fn insert_account(&mut self, address: Address, account: AccountInfo) { - self.insert_account_info(address.into(), account) + self.insert_account_info(h160_to_b160(address), account) } fn set_storage_at(&mut self, address: Address, slot: U256, val: U256) -> DatabaseResult<()> { - self.insert_account_storage(address.into(), slot.into(), val.into()) + self.insert_account_storage(h160_to_b160(address), u256_to_ru256(slot), u256_to_ru256(val)) } fn insert_block_hash(&mut self, number: U256, hash: H256) { - self.block_hashes.insert(number.into(), hash.into()); + self.block_hashes.insert(u256_to_ru256(number), h256_to_b256(hash)); } fn dump_state(&self) -> DatabaseResult> { diff --git a/crates/anvil/src/eth/backend/executor.rs b/crates/anvil/src/eth/backend/executor.rs index 7198e160cd0ab..ddbfb7f9d1931 100644 --- a/crates/anvil/src/eth/backend/executor.rs +++ b/crates/anvil/src/eth/backend/executor.rs @@ -170,8 +170,8 @@ impl<'a, DB: Db + ?Sized, Validator: TransactionValidator> TransactionExecutor<' traces: CallTraceArena { arena: traces }, exit, out: match out { - Some(Output::Call(b)) => Some(b.into()), - Some(Output::Create(b, _)) => Some(b.into()), + Some(Output::Call(b)) => Some(ethers::types::Bytes(b.0)), + Some(Output::Create(b, _)) => Some(ethers::types::Bytes(b.0)), _ => None, }, }; @@ -190,15 +190,15 @@ impl<'a, DB: Db + ?Sized, Validator: TransactionValidator> TransactionExecutor<' state_root: self.db.maybe_state_root().unwrap_or_default(), receipts_root, logs_bloom: bloom, - difficulty: difficulty.into(), - number: block_number.into(), - gas_limit: gas_limit.into(), + difficulty: ru256_to_u256(difficulty), + number: ru256_to_u256(block_number), + gas_limit: ru256_to_u256(gas_limit), gas_used: cumulative_gas_used, timestamp, extra_data: Default::default(), mix_hash: Default::default(), nonce: Default::default(), - base_fee: base_fee.map(|x| x.into()), + base_fee: base_fee.map(ru256_to_u256), }; let block = Block::new(partial_header, transactions.clone(), ommers); @@ -238,7 +238,7 @@ impl<'a, 'b, DB: Db + ?Sized, Validator: TransactionValidator> Iterator let env = self.env_for(&transaction.pending_transaction); // check that we comply with the block's gas limit let max_gas = self.gas_used.saturating_add(U256::from(env.tx.gas_limit)); - if max_gas > env.block.gas_limit.into() { + if max_gas > ru256_to_u256(env.block.gas_limit) { return Some(TransactionExecutionOutcome::Exhausted(transaction)) } diff --git a/crates/anvil/src/eth/backend/genesis.rs b/crates/anvil/src/eth/backend/genesis.rs index 4f1c0f92c3a96..25cc3207dc97a 100644 --- a/crates/anvil/src/eth/backend/genesis.rs +++ b/crates/anvil/src/eth/backend/genesis.rs @@ -4,6 +4,7 @@ use crate::{ eth::backend::db::{Db, MaybeHashDatabase}, genesis::Genesis, }; +use alloy_primitives::{Address as B160, B256, U256}; use ethers::{ abi::ethereum_types::BigEndianHash, types::{Address, H256}, @@ -13,8 +14,8 @@ use foundry_evm::{ backend::{snapshot::StateSnapshot, DatabaseError, DatabaseResult}, DatabaseRef, }, - revm::primitives::{AccountInfo, Bytecode, B160, B256, KECCAK_EMPTY, U256}, - utils::b160_to_h160, + revm::primitives::{AccountInfo, Bytecode, KECCAK_EMPTY}, + utils::{b160_to_h160, ru256_to_u256, u256_to_ru256}, }; use parking_lot::Mutex; use std::{collections::HashMap, sync::Arc}; @@ -103,7 +104,7 @@ pub(crate) struct AtGenesisStateDb<'a> { impl<'a> DatabaseRef for AtGenesisStateDb<'a> { type Error = DatabaseError; fn basic(&self, address: B160) -> DatabaseResult> { - if let Some(acc) = self.accounts.get(&address.into()).cloned() { + if let Some(acc) = self.accounts.get(&b160_to_h160(address)).cloned() { return Ok(Some(acc)) } self.db.basic(address) @@ -122,9 +123,12 @@ impl<'a> DatabaseRef for AtGenesisStateDb<'a> { .as_ref() .and_then(|genesis| genesis.alloc.accounts.get(&b160_to_h160(address))) { - let value = - acc.storage.get(&H256::from_uint(&index.into())).copied().unwrap_or_default(); - return Ok(value.into_uint().into()) + let value = acc + .storage + .get(&H256::from_uint(&ru256_to_u256(index))) + .copied() + .unwrap_or_default(); + return Ok(u256_to_ru256(value.into_uint())) } self.db.storage(address, index) } diff --git a/crates/anvil/src/eth/backend/mem/fork_db.rs b/crates/anvil/src/eth/backend/mem/fork_db.rs index 593fae025a7e5..bb6b4e1bd91f4 100644 --- a/crates/anvil/src/eth/backend/mem/fork_db.rs +++ b/crates/anvil/src/eth/backend/mem/fork_db.rs @@ -13,6 +13,7 @@ use foundry_evm::{ fork::database::ForkDbSnapshot, }, revm::Database, + utils::{b160_to_h160, h160_to_b160, h256_to_b256, ru256_to_u256, u256_to_ru256}, }; /// Implement the helper for the fork database @@ -23,12 +24,12 @@ impl Db for ForkedDatabase { fn set_storage_at(&mut self, address: Address, slot: U256, val: U256) -> DatabaseResult<()> { // this ensures the account is loaded first - let _ = Database::basic(self, address.into())?; + let _ = Database::basic(self, h160_to_b160(address))?; self.database_mut().set_storage_at(address, slot, val) } fn insert_block_hash(&mut self, number: U256, hash: H256) { - self.inner().block_hashes().write().insert(number.into(), hash.into()); + self.inner().block_hashes().write().insert(u256_to_ru256(number), h256_to_b256(hash)); } fn dump_state(&self) -> DatabaseResult> { @@ -46,15 +47,15 @@ impl Db for ForkedDatabase { } .to_checked(); Ok(( - k.into(), + b160_to_h160(k), SerializableAccountRecord { nonce: v.info.nonce, - balance: v.info.balance.into(), + balance: ru256_to_u256(v.info.balance), code: code.bytes()[..code.len()].to_vec().into(), storage: v .storage .into_iter() - .map(|kv| (kv.0.into(), kv.1.into())) + .map(|kv| (ru256_to_u256(kv.0), ru256_to_u256(kv.1))) .collect(), }, )) @@ -64,11 +65,11 @@ impl Db for ForkedDatabase { } fn snapshot(&mut self) -> U256 { - self.insert_snapshot() + ru256_to_u256(self.insert_snapshot()) } fn revert(&mut self, id: U256) -> bool { - self.revert_snapshot(id) + self.revert_snapshot(u256_to_ru256(id)) } fn current_state(&self) -> StateDb { diff --git a/crates/anvil/src/eth/backend/mem/in_memory_db.rs b/crates/anvil/src/eth/backend/mem/in_memory_db.rs index 18b0c83690ef7..23733f168a38e 100644 --- a/crates/anvil/src/eth/backend/mem/in_memory_db.rs +++ b/crates/anvil/src/eth/backend/mem/in_memory_db.rs @@ -9,7 +9,7 @@ use crate::{ Address, U256, }; use ethers::prelude::H256; -use foundry_evm::utils::h160_to_b160; +use foundry_evm::utils::{b160_to_h160, h160_to_b160, h256_to_b256, ru256_to_u256, u256_to_ru256}; use tracing::{trace, warn}; // reexport for convenience @@ -19,15 +19,19 @@ pub use foundry_evm::executor::{backend::MemDb, DatabaseRef}; impl Db for MemDb { fn insert_account(&mut self, address: Address, account: AccountInfo) { - self.inner.insert_account_info(address.into(), account) + self.inner.insert_account_info(h160_to_b160(address), account) } fn set_storage_at(&mut self, address: Address, slot: U256, val: U256) -> DatabaseResult<()> { - self.inner.insert_account_storage(address.into(), slot.into(), val.into()) + self.inner.insert_account_storage( + h160_to_b160(address), + u256_to_ru256(slot), + u256_to_ru256(val), + ) } fn insert_block_hash(&mut self, number: U256, hash: H256) { - self.inner.block_hashes.insert(number.into(), hash.into()); + self.inner.block_hashes.insert(u256_to_ru256(number), h256_to_b256(hash)); } fn dump_state(&self) -> DatabaseResult> { @@ -44,12 +48,16 @@ impl Db for MemDb { } .to_checked(); Ok(( - k.into(), + b160_to_h160(k), SerializableAccountRecord { nonce: v.info.nonce, - balance: v.info.balance.into(), + balance: ru256_to_u256(v.info.balance), code: code.bytes()[..code.len()].to_vec().into(), - storage: v.storage.into_iter().map(|k| (k.0.into(), k.1.into())).collect(), + storage: v + .storage + .into_iter() + .map(|k| (ru256_to_u256(k.0), ru256_to_u256(k.1))) + .collect(), }, )) }) @@ -62,11 +70,11 @@ impl Db for MemDb { fn snapshot(&mut self) -> U256 { let id = self.snapshots.insert(self.inner.clone()); trace!(target: "backend::memdb", "Created new snapshot {}", id); - id + ru256_to_u256(id) } fn revert(&mut self, id: U256) -> bool { - if let Some(snapshot) = self.snapshots.remove(id) { + if let Some(snapshot) = self.snapshots.remove(u256_to_ru256(id)) { self.inner = snapshot; trace!(target: "backend::memdb", "Reverted snapshot {}", id); true @@ -118,11 +126,13 @@ mod tests { revm::primitives::AccountInfo, Address, }; + use alloy_primitives::U256 as rU256; use bytes::Bytes; use ethers::types::U256; use foundry_evm::{ executor::{backend::MemDb, DatabaseRef}, - revm::primitives::{Bytecode, KECCAK_EMPTY, U256 as rU256}, + revm::primitives::{Bytecode, KECCAK_EMPTY}, + utils::h160_to_b160, }; use std::{collections::BTreeMap, str::FromStr}; @@ -136,7 +146,8 @@ mod tests { let mut dump_db = MemDb::default(); let contract_code: Bytecode = - Bytecode::new_raw(Bytes::from("fake contract code")).to_checked(); + Bytecode::new_raw(alloy_primitives::Bytes(Bytes::from("fake contract code"))) + .to_checked(); dump_db.insert_account( test_addr, @@ -148,7 +159,7 @@ mod tests { }, ); - dump_db.set_storage_at(test_addr, "0x1234567".into(), "0x1".into()).unwrap(); + dump_db.set_storage_at(test_addr, U256::from(1234567), U256::from(1)).unwrap(); let state = dump_db.dump_state().unwrap().unwrap(); @@ -156,14 +167,14 @@ mod tests { load_db.load_state(state).unwrap(); - let loaded_account = load_db.basic(test_addr.into()).unwrap().unwrap(); + let loaded_account = load_db.basic(h160_to_b160(test_addr)).unwrap().unwrap(); assert_eq!(loaded_account.balance, rU256::from(123456)); assert_eq!(load_db.code_by_hash(loaded_account.code_hash).unwrap(), contract_code); assert_eq!(loaded_account.nonce, 1234); assert_eq!( - load_db.storage(test_addr.into(), Into::::into("0x1234567").into()).unwrap(), - Into::::into("0x1").into() + load_db.storage(h160_to_b160(test_addr), rU256::from(1234567)).unwrap(), + rU256::from(1) ); } @@ -177,7 +188,8 @@ mod tests { Address::from_str("0x70997970c51812dc3a010c7d01b50e0d17dc79c8").unwrap(); let contract_code: Bytecode = - Bytecode::new_raw(Bytes::from("fake contract code")).to_checked(); + Bytecode::new_raw(alloy_primitives::Bytes(Bytes::from("fake contract code"))) + .to_checked(); let mut db = MemDb::default(); @@ -191,8 +203,8 @@ mod tests { }, ); - db.set_storage_at(test_addr, "0x1234567".into(), "0x1".into()).unwrap(); - db.set_storage_at(test_addr, "0x1234568".into(), "0x2".into()).unwrap(); + db.set_storage_at(test_addr, U256::from(1234567), U256::from(1)).unwrap(); + db.set_storage_at(test_addr, U256::from(1234568), U256::from(2)).unwrap(); let mut new_state = SerializableState::default(); @@ -207,7 +219,7 @@ mod tests { ); let mut new_storage = BTreeMap::default(); - new_storage.insert("0x1234568".into(), "0x5".into()); + new_storage.insert(U256::from(1234568), U256::from(5)); new_state.accounts.insert( test_addr, @@ -221,8 +233,8 @@ mod tests { db.load_state(new_state).unwrap(); - let loaded_account = db.basic(test_addr.into()).unwrap().unwrap(); - let loaded_account2 = db.basic(test_addr2.into()).unwrap().unwrap(); + let loaded_account = db.basic(h160_to_b160(test_addr)).unwrap().unwrap(); + let loaded_account2 = db.basic(h160_to_b160(test_addr2)).unwrap().unwrap(); assert_eq!(loaded_account2.nonce, 1); @@ -230,12 +242,12 @@ mod tests { assert_eq!(db.code_by_hash(loaded_account.code_hash).unwrap(), contract_code); assert_eq!(loaded_account.nonce, 1234); assert_eq!( - db.storage(test_addr.into(), Into::::into("0x1234567").into()).unwrap(), - Into::::into("0x1").into() + db.storage(h160_to_b160(test_addr), rU256::from(1234567)).unwrap(), + rU256::from(1) ); assert_eq!( - db.storage(test_addr.into(), Into::::into("0x1234568").into()).unwrap(), - Into::::into("0x5").into() + db.storage(h160_to_b160(test_addr), rU256::from(1234568)).unwrap(), + rU256::from(5) ); } } diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index 9ca7686c618b5..2f83ee97a116f 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -1,7 +1,6 @@ //! Anvil specific [`revm::Inspector`] implementation use crate::{eth::macros::node_info, revm::Database}; -use bytes::Bytes; use ethers::types::Log; use foundry_evm::{ call_inspectors, @@ -10,7 +9,7 @@ use foundry_evm::{ revm, revm::{ interpreter::{CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}, - primitives::{B160, B256}, + primitives::{Address as rAddress, Bytes, B256}, EVMData, }, }; @@ -72,7 +71,7 @@ impl revm::Inspector for Inspector { fn log( &mut self, evm_data: &mut EVMData<'_, DB>, - address: &B160, + address: &rAddress, topics: &[B256], data: &Bytes, ) { @@ -127,7 +126,7 @@ impl revm::Inspector for Inspector { &mut self, data: &mut EVMData<'_, DB>, call: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option, Gas, Bytes) { call_inspectors!([&mut self.tracer], |inspector| { inspector.create(data, call); }); @@ -141,10 +140,10 @@ impl revm::Inspector for Inspector { data: &mut EVMData<'_, DB>, inputs: &CreateInputs, status: InstructionResult, - address: Option, + address: Option, gas: Gas, retdata: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option, Gas, Bytes) { call_inspectors!([&mut self.tracer], |inspector| { inspector.create_end(data, inputs, status, address, gas, retdata.clone()); }); diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index b443ea2e365d0..ec0f7a3a64c66 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -72,8 +72,8 @@ use foundry_evm::{ }, }, utils::{ - eval_to_instruction_result, h256_to_b256, halt_to_instruction_result, ru256_to_u256, - u256_to_h256_be, u256_to_ru256, + b160_to_h160, eval_to_instruction_result, h160_to_b160, h256_to_b256, + halt_to_instruction_result, ru256_to_u256, u256_to_h256_be, u256_to_ru256, }, }; use futures::channel::mpsc::{unbounded, UnboundedSender}; @@ -264,7 +264,7 @@ impl Backend { // accounts concurrently by spawning the job to a new task genesis_accounts_futures.push(tokio::task::spawn(async move { let db = db.read().await; - let info = db.basic(address.into())?.unwrap_or_default(); + let info = db.basic(h160_to_b160(address))?.unwrap_or_default(); Ok::<_, DatabaseError>((address, info)) })); } @@ -338,7 +338,7 @@ impl Backend { /// Returns the `AccountInfo` from the database pub async fn get_account(&self, address: Address) -> DatabaseResult { - Ok(self.db.read().await.basic(address.into())?.unwrap_or_default()) + Ok(self.db.read().await.basic(h160_to_b160(address))?.unwrap_or_default()) } /// Whether we're forked off some remote client @@ -369,9 +369,9 @@ impl Backend { env.block = BlockEnv { number: rU256::from(fork_block_number), - timestamp: fork_block.timestamp.into(), - gas_limit: fork_block.gas_limit.into(), - difficulty: fork_block.difficulty.into(), + timestamp: u256_to_ru256(fork_block.timestamp), + gas_limit: u256_to_ru256(fork_block.gas_limit), + difficulty: u256_to_ru256(fork_block.difficulty), prevrandao: fork_block.mix_hash.map(h256_to_b256), // Keep previous `coinbase` and `basefee` value coinbase: env.block.coinbase, @@ -379,7 +379,7 @@ impl Backend { }; self.time.reset(ru256_to_u256(env.block.timestamp).as_u64()); - self.fees.set_base_fee(env.block.basefee.into()); + self.fees.set_base_fee(ru256_to_u256(env.block.basefee)); // also reset the total difficulty self.blockchain.storage.write().total_difficulty = fork.total_difficulty(); @@ -450,12 +450,12 @@ impl Backend { /// Sets the block number pub fn set_block_number(&self, number: U256) { let mut env = self.env.write(); - env.block.number = number.into(); + env.block.number = u256_to_ru256(number); } /// Returns the client coinbase address. pub fn coinbase(&self) -> Address { - self.env.read().block.coinbase.into() + b160_to_h160(self.env.read().block.coinbase) } /// Returns the client coinbase address. @@ -465,7 +465,7 @@ impl Backend { /// Returns balance of the given account. pub async fn current_balance(&self, address: Address) -> DatabaseResult { - Ok(self.get_account(address).await?.balance.into()) + Ok(self.get_account(address).await?.balance).map(ru256_to_u256) } /// Returns balance of the given account. @@ -475,7 +475,7 @@ impl Backend { /// Sets the coinbase address pub fn set_coinbase(&self, address: Address) { - self.env.write().block.coinbase = address.into(); + self.env.write().block.coinbase = h160_to_b160(address); } /// Sets the nonce of the given address @@ -541,12 +541,12 @@ impl Backend { /// Returns the block gas limit pub fn gas_limit(&self) -> U256 { - self.env.read().block.gas_limit.into() + ru256_to_u256(self.env.read().block.gas_limit) } /// Sets the block gas limit pub fn set_gas_limit(&self, gas_limit: U256) { - self.env.write().block.gas_limit = gas_limit.into(); + self.env.write().block.gas_limit = u256_to_ru256(gas_limit); } /// Returns the current base fee @@ -685,7 +685,7 @@ impl Backend { let mut env = self.env.read().clone(); // increase block number for this block env.block.number = env.block.number.saturating_add(rU256::from(1)); - env.block.basefee = self.base_fee().into(); + env.block.basefee = u256_to_ru256(self.base_fee()); env.block.timestamp = rU256::from(self.time.current_call_timestamp()); env } @@ -712,7 +712,7 @@ impl Backend { }; let state = result_and_state.state; let state: revm::primitives::HashMap = - state.into_iter().map(|kv| (kv.0.into(), kv.1)).collect(); + state.into_iter().map(|kv| (b160_to_h160(kv.0), kv.1)).collect(); let (exit_reason, gas_used, out, logs) = match result_and_state.result { ExecutionResult::Success { reason, gas_used, logs, output, .. } => { (eval_to_instruction_result(reason), gas_used, Some(output), Some(logs)) @@ -801,7 +801,7 @@ impl Backend { // increase block number for this block env.block.number = env.block.number.saturating_add(rU256::from(1)); - env.block.basefee = current_base_fee.into(); + env.block.basefee = u256_to_ru256(current_base_fee); env.block.timestamp = rU256::from(self.time.next_timestamp()); let best_hash = self.blockchain.storage.read().best_hash; @@ -1007,7 +1007,7 @@ impl Backend { let FeeDetails { gas_price, max_fee_per_gas, max_priority_fee_per_gas } = fee_details; - let gas_limit = gas.unwrap_or(block_env.gas_limit.into()); + let gas_limit = gas.unwrap_or(ru256_to_u256(block_env.gas_limit)); let mut env = self.env.read().clone(); env.block = block_env; // we want to disable this in eth_call, since this is common practice used by other node @@ -1015,22 +1015,22 @@ impl Backend { env.cfg.disable_block_gas_limit = true; if let Some(base) = max_fee_per_gas { - env.block.basefee = base.into(); + env.block.basefee = u256_to_ru256(base); } let gas_price = gas_price.or(max_fee_per_gas).unwrap_or_else(|| self.gas_price()); let caller = from.unwrap_or_default(); env.tx = TxEnv { - caller: caller.into(), + caller: h160_to_b160(caller), gas_limit: gas_limit.as_u64(), - gas_price: gas_price.into(), + gas_price: u256_to_ru256(gas_price), gas_priority_fee: max_priority_fee_per_gas.map(u256_to_ru256), transact_to: match to { - Some(addr) => TransactTo::Call(addr.into()), + Some(addr) => TransactTo::Call(h160_to_b160(addr)), None => TransactTo::Create(CreateScheme::Create), }, - value: value.unwrap_or_default().into(), + value: value.map(u256_to_ru256).unwrap_or_default(), data: data.unwrap_or_default().to_vec().into(), chain_id: None, nonce: nonce.map(|n| n.as_u64()), @@ -1072,7 +1072,7 @@ impl Backend { }; let state = result_and_state.state; let state: revm::primitives::HashMap = - state.into_iter().map(|kv| (kv.0.into(), kv.1)).collect(); + state.into_iter().map(|kv| (b160_to_h160(kv.0), kv.1)).collect(); let (exit_reason, gas_used, out) = match result_and_state.result { ExecutionResult::Success { reason, gas_used, output, .. } => { (eval_to_instruction_result(reason), gas_used, Some(output)) @@ -1138,15 +1138,15 @@ impl Backend { let to = if let Some(to) = request.to { to } else { - let nonce = state.basic(from.into())?.unwrap_or_default().nonce; + let nonce = state.basic(h160_to_b160(from))?.unwrap_or_default().nonce; get_contract_address(from, nonce) }; let mut tracer = AccessListTracer::new( AccessList(request.access_list.clone().unwrap_or_default()), - from, - to, - self.precompiles(), + h160_to_b160(from), + h160_to_b160(to), + self.precompiles().into_iter().map(h160_to_b160).collect(), ); let mut evm = revm::EVM::new(); @@ -1585,13 +1585,15 @@ impl Backend { .with_pending_block(pool_transactions, |state, block| { let block = block.block; let block = BlockEnv { - number: block.header.number.into(), - coinbase: block.header.beneficiary.into(), + number: u256_to_ru256(block.header.number), + coinbase: h160_to_b160(block.header.beneficiary), timestamp: rU256::from(block.header.timestamp), - difficulty: block.header.difficulty.into(), - prevrandao: Some(block.header.mix_hash.into()), - basefee: block.header.base_fee_per_gas.unwrap_or_default().into(), - gas_limit: block.header.gas_limit.into(), + difficulty: u256_to_ru256(block.header.difficulty), + prevrandao: Some(block.header.mix_hash).map(h256_to_b256), + basefee: u256_to_ru256( + block.header.base_fee_per_gas.unwrap_or_default(), + ), + gas_limit: u256_to_ru256(block.header.gas_limit), }; f(state, block) }) @@ -1603,7 +1605,7 @@ impl Backend { }; let block_number: U256 = self.convert_block_number(block_number).into(); - if block_number < self.env.read().block.number.into() { + if u256_to_ru256(block_number) < self.env.read().block.number { { let mut states = self.states.write(); @@ -1612,13 +1614,13 @@ impl Backend { .and_then(|block| Some((states.get(&block.header.hash())?, block))) { let block = BlockEnv { - number: block.header.number.into(), - coinbase: block.header.beneficiary.into(), + number: u256_to_ru256(block.header.number), + coinbase: h160_to_b160(block.header.beneficiary), timestamp: rU256::from(block.header.timestamp), - difficulty: block.header.difficulty.into(), - prevrandao: Some(block.header.mix_hash).map(Into::into), - basefee: block.header.base_fee_per_gas.unwrap_or_default().into(), - gas_limit: block.header.gas_limit.into(), + difficulty: u256_to_ru256(block.header.difficulty), + prevrandao: Some(block.header.mix_hash).map(h256_to_b256), + basefee: u256_to_ru256(block.header.base_fee_per_gas.unwrap_or_default()), + gas_limit: u256_to_ru256(block.header.gas_limit), }; return Ok(f(Box::new(state), block)) } @@ -1635,9 +1637,9 @@ impl Backend { let db = self.db.read().await; let gen_db = self.genesis.state_db_at_genesis(Box::new(&*db)); - block.number = block_number.into(); + block.number = u256_to_ru256(block_number); block.timestamp = rU256::from(fork.timestamp()); - block.basefee = fork.base_fee().unwrap_or_default().into(); + block.basefee = u256_to_ru256(fork.base_fee().unwrap_or_default()); return Ok(f(Box::new(&gen_db), block)) } @@ -1663,7 +1665,7 @@ impl Backend { ) -> Result { self.with_database_at(block_request, |db, _| { trace!(target: "backend", "get storage for {:?} at {:?}", address, index); - let val = db.storage(address.into(), index.into())?; + let val = db.storage(h160_to_b160(address), u256_to_ru256(index))?; Ok(u256_to_h256_be(ru256_to_u256(val))) }) .await? @@ -1690,7 +1692,7 @@ impl Backend { D: DatabaseRef, { trace!(target: "backend", "get code for {:?}", address); - let account = state.basic(address.into())?.unwrap_or_default(); + let account = state.basic(h160_to_b160(address))?.unwrap_or_default(); if account.code_hash == KECCAK_EMPTY { // if the code hash is `KECCAK_EMPTY`, we check no further return Ok(Default::default()) @@ -1724,7 +1726,7 @@ impl Backend { D: DatabaseRef, { trace!(target: "backend", "get balance for {:?}", address); - Ok(state.basic(address.into())?.unwrap_or_default().balance.into()) + Ok(state.basic(h160_to_b160(address))?.unwrap_or_default().balance).map(ru256_to_u256) } /// Returns the nonce of the address @@ -1747,7 +1749,7 @@ impl Backend { }; self.with_database_at(final_block_request, |db, _| { trace!(target: "backend", "get nonce for {:?}", address); - Ok(db.basic(address.into())?.unwrap_or_default().nonce.into()) + Ok(db.basic(h160_to_b160(address))?.unwrap_or_default().nonce.into()) }) .await? } @@ -2189,7 +2191,7 @@ impl TransactionValidator for Backend { } // Check gas limit, iff block gas limit is set. - if !env.cfg.disable_block_gas_limit && tx.gas_limit() > env.block.gas_limit.into() { + if !env.cfg.disable_block_gas_limit && tx.gas_limit() > ru256_to_u256(env.block.gas_limit) { warn!(target: "backend", "[{:?}] gas too high", tx.hash()); return Err(InvalidTransactionError::GasTooHigh(ErrDetail { detail: String::from("tx.gas_limit > env.block.gas_limit"), @@ -2205,7 +2207,7 @@ impl TransactionValidator for Backend { } if (env.cfg.spec_id as u8) >= (SpecId::LONDON as u8) { - if tx.gas_price() < env.block.basefee.into() { + if tx.gas_price() < ru256_to_u256(env.block.basefee) { warn!(target: "backend", "max fee per gas={}, too low, block basefee={}",tx.gas_price(), env.block.basefee); return Err(InvalidTransactionError::FeeCapTooLow) } @@ -2229,7 +2231,7 @@ impl TransactionValidator for Backend { InvalidTransactionError::InsufficientFunds })?; - if account.balance < req_funds.into() { + if account.balance < u256_to_ru256(req_funds) { warn!(target: "backend", "[{:?}] insufficient allowance={}, required={} account={:?}", tx.hash(), account.balance, req_funds, *pending.sender()); return Err(InvalidTransactionError::InsufficientFunds) } diff --git a/crates/anvil/src/eth/backend/mem/state.rs b/crates/anvil/src/eth/backend/mem/state.rs index b36f8bf8df923..ad90b6bddb192 100644 --- a/crates/anvil/src/eth/backend/mem/state.rs +++ b/crates/anvil/src/eth/backend/mem/state.rs @@ -1,6 +1,7 @@ //! Support for generating the state root for memdb storage use crate::eth::{backend::db::AsHashDB, error::BlockchainError}; +use alloy_primitives::{Address as rAddress, U256 as rU256}; use anvil_core::eth::{state::StateOverride, trie::RefSecTrieDBMut}; use bytes::Bytes; use ethers::{ @@ -12,9 +13,9 @@ use foundry_evm::{ executor::{backend::DatabaseError, DatabaseRef}, revm::{ db::{CacheDB, DbAccount}, - primitives::{AccountInfo, Bytecode, Log, B160, U256 as rU256}, + primitives::{AccountInfo, Bytecode, Log}, }, - utils::{b160_to_h160, b256_to_h256, ru256_to_u256, u256_to_ru256}, + utils::{b160_to_h160, b256_to_h256, h160_to_b160, ru256_to_u256, u256_to_ru256}, HashMap as Map, }; use memory_db::HashKey; @@ -31,7 +32,7 @@ pub fn log_rlp_hash(logs: Vec) -> H256 { stream.begin_list(3); stream.append(&b160_to_h160(log.address)); stream.append_list(&topics); - stream.append(&log.data); + stream.append(&log.data.0); } stream.finalize_unbounded_list(); let out = stream.out().freeze(); @@ -52,7 +53,7 @@ pub fn storage_trie_db(storage: &Map) -> (AsHashDB, H256) { let mut temp: [u8; 32] = [0; 32]; ru256_to_u256(*k).to_big_endian(&mut temp); let key = H256::from(temp); - let value = rlp::encode(v); + let value = rlp::encode(&ru256_to_u256(*v)); trie.insert(key.as_bytes(), value.as_ref()).unwrap(); } } @@ -63,7 +64,7 @@ pub fn storage_trie_db(storage: &Map) -> (AsHashDB, H256) { } /// Returns the account data as `HashDB` -pub fn trie_hash_db(accounts: &Map) -> (AsHashDB, H256) { +pub fn trie_hash_db(accounts: &Map) -> (AsHashDB, H256) { let accounts = trie_accounts(accounts); // Populate DB with full trie from entries. @@ -83,7 +84,7 @@ pub fn trie_hash_db(accounts: &Map) -> (AsHashDB, H256) { } /// Returns all RLP-encoded Accounts -pub fn trie_accounts(accounts: &Map) -> Vec<(B160, Bytes)> { +pub fn trie_accounts(accounts: &Map) -> Vec<(rAddress, Bytes)> { accounts .iter() .map(|(address, account)| { @@ -93,7 +94,7 @@ pub fn trie_accounts(accounts: &Map) -> Vec<(B160, Bytes)> { .collect() } -pub fn state_merkle_trie_root(accounts: &Map) -> H256 { +pub fn state_merkle_trie_root(accounts: &Map) -> H256 { trie_hash_db(accounts).1 } @@ -101,9 +102,9 @@ pub fn state_merkle_trie_root(accounts: &Map) -> H256 { pub fn trie_account_rlp(info: &AccountInfo, storage: &Map) -> Bytes { let mut stream = RlpStream::new_list(4); stream.append(&info.nonce); - stream.append(&info.balance); + stream.append(&ru256_to_u256(info.balance)); stream.append(&storage_trie_db(storage).1); - stream.append(&info.code_hash.as_bytes()); + stream.append(&info.code_hash.as_slice()); stream.out().freeze() } @@ -117,7 +118,7 @@ where { let mut cache_db = CacheDB::new(state); for (account, account_overrides) in overrides.iter() { - let mut account_info = cache_db.basic((*account).into())?.unwrap_or_default(); + let mut account_info = cache_db.basic(h160_to_b160(*account))?.unwrap_or_default(); if let Some(nonce) = account_overrides.nonce { account_info.nonce = nonce; @@ -126,10 +127,10 @@ where account_info.code = Some(Bytecode::new_raw(code.to_vec().into())); } if let Some(balance) = account_overrides.balance { - account_info.balance = balance.into(); + account_info.balance = u256_to_ru256(balance); } - cache_db.insert_account_info((*account).into(), account_info); + cache_db.insert_account_info(h160_to_b160(*account), account_info); // We ensure that not both state and state_diff are set. // If state is set, we must mark the account as "NewlyCreated", so that the old storage @@ -143,7 +144,7 @@ where (None, None) => (), (Some(new_account_state), None) => { cache_db.replace_account_storage( - (*account).into(), + h160_to_b160(*account), new_account_state .iter() .map(|(key, value)| { @@ -155,9 +156,9 @@ where (None, Some(account_state_diff)) => { for (key, value) in account_state_diff.iter() { cache_db.insert_account_storage( - (*account).into(), - key.into_uint().into(), - value.into_uint().into(), + h160_to_b160(*account), + u256_to_ru256(key.into_uint()), + u256_to_ru256(value.into_uint()), )?; } } diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index 17f65910c8144..bbd379c30fe50 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -15,7 +15,10 @@ use ethers::{ prelude::{BlockId, BlockNumber, DefaultFrame, Trace, H256, H256 as TxHash, U64}, types::{ActionType, Bytes, GethDebugTracingOptions, TransactionReceipt, U256}, }; -use foundry_evm::revm::{interpreter::InstructionResult, primitives::Env}; +use foundry_evm::{ + revm::{interpreter::InstructionResult, primitives::Env}, + utils::{b160_to_h160, ru256_to_u256}, +}; use parking_lot::RwLock; use std::{ collections::{HashMap, VecDeque}, @@ -226,9 +229,9 @@ impl BlockchainStorage { let partial_header = PartialHeader { timestamp, base_fee, - gas_limit: env.block.gas_limit.into(), - beneficiary: env.block.coinbase.into(), - difficulty: env.block.difficulty.into(), + gas_limit: ru256_to_u256(env.block.gas_limit), + beneficiary: b160_to_h160(env.block.coinbase), + difficulty: ru256_to_u256(env.block.difficulty), ..Default::default() }; let block = Block::new::(partial_header, vec![], vec![]); @@ -429,6 +432,7 @@ mod tests { db::DatabaseRef, primitives::{AccountInfo, U256 as rU256}, }, + utils::h160_to_b160, }; #[test] @@ -459,7 +463,7 @@ mod tests { let loaded = storage.get(&one).unwrap(); - let acc = loaded.basic(addr.into()).unwrap().unwrap(); + let acc = loaded.basic(h160_to_b160(addr)).unwrap().unwrap(); assert_eq!(acc.balance, rU256::from(1337u64)); } @@ -489,7 +493,7 @@ mod tests { let hash = H256::from_uint(&U256::from(idx)); let addr = Address::from(hash); let loaded = storage.get(&hash).unwrap(); - let acc = loaded.basic(addr.into()).unwrap().unwrap(); + let acc = loaded.basic(h160_to_b160(addr)).unwrap().unwrap(); let balance = (idx * 2) as u64; assert_eq!(acc.balance, rU256::from(balance)); } diff --git a/crates/anvil/src/genesis.rs b/crates/anvil/src/genesis.rs index 093ab0ddb0d50..52deb5b27b0a0 100644 --- a/crates/anvil/src/genesis.rs +++ b/crates/anvil/src/genesis.rs @@ -7,7 +7,7 @@ use ethers::{ use foundry_common::errors::FsPathError; use foundry_evm::{ revm::primitives::{Bytecode, Env, KECCAK_EMPTY, U256 as rU256}, - utils::h160_to_b160, + utils::{h160_to_b160, u256_to_ru256}, }; use serde::{Deserialize, Serialize}; use std::{ @@ -92,7 +92,7 @@ impl Genesis { env.block.timestamp = rU256::from(timestamp); } if let Some(base_fee) = self.base_fee_per_gas { - env.block.basefee = base_fee.into(); + env.block.basefee = u256_to_ru256(base_fee); } if let Some(number) = self.number { env.block.number = rU256::from(number); @@ -144,7 +144,7 @@ impl From for AccountInfo { let GenesisAccount { code, balance, nonce, .. } = acc; let code = code.map(|code| Bytecode::new_raw(code.to_vec().into())); AccountInfo { - balance: balance.into(), + balance: u256_to_ru256(balance), nonce: nonce.unwrap_or_default(), code_hash: code.as_ref().map(|code| code.hash_slow()).unwrap_or(KECCAK_EMPTY), code, diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index c539445be2b6d..2ea81e2519d1b 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -15,7 +15,7 @@ use ethers::{ }; use foundry_common::get_http_provider; use foundry_config::Config; -use foundry_evm::utils::h160_to_b160; +use foundry_evm::utils::{h160_to_b160, u256_to_ru256}; use foundry_utils::{rpc, rpc::next_http_rpc_endpoint}; use futures::StreamExt; use std::{sync::Arc, time::Duration}; @@ -280,7 +280,7 @@ async fn test_separate_states() { let fork_db = fork.database.read().await; let acc = fork_db.inner().db().accounts.read().get(&h160_to_b160(addr)).cloned().unwrap(); - assert_eq!(acc.balance, remote_balance.into()) + assert_eq!(acc.balance, u256_to_ru256(remote_balance)) } #[tokio::test(flavor = "multi_thread")] diff --git a/crates/anvil/tests/it/proof/mod.rs b/crates/anvil/tests/it/proof/mod.rs index c82de8a2f5d8f..e56e8169ba8af 100644 --- a/crates/anvil/tests/it/proof/mod.rs +++ b/crates/anvil/tests/it/proof/mod.rs @@ -11,7 +11,7 @@ use anvil_core::eth::proof::{AccountProof, BasicAccount}; use crate::proof::eip1186::verify_proof; use anvil_core::eth::trie::ExtensionLayout; use ethers::utils::{keccak256, rlp}; -use foundry_evm::revm::primitives::KECCAK_EMPTY; +use foundry_evm::{revm::primitives::KECCAK_EMPTY, utils::b256_to_h256}; mod eip1186; @@ -32,7 +32,7 @@ async fn can_get_proof() { nonce: 0.into(), balance: 0.into(), storage_root: proof.storage_hash, - code_hash: KECCAK_EMPTY.into(), + code_hash: b256_to_h256(KECCAK_EMPTY), }; let rlp_account = rlp::encode(&account); diff --git a/crates/cast/bin/cmd/call.rs b/crates/cast/bin/cmd/call.rs index ec89196590131..08e759610be68 100644 --- a/crates/cast/bin/cmd/call.rs +++ b/crates/cast/bin/cmd/call.rs @@ -11,7 +11,11 @@ use foundry_cli::{ }; use foundry_common::runtime_client::RuntimeClient; use foundry_config::{find_project_root_path, Config}; -use foundry_evm::{executor::opts::EvmOpts, trace::TracingExecutor}; +use foundry_evm::{ + executor::opts::EvmOpts, + trace::TracingExecutor, + utils::{h160_to_b160, u256_to_ru256}, +}; use std::str::FromStr; type Provider = ethers::providers::Provider; @@ -155,9 +159,9 @@ impl CallArgs { .await; let trace = match executor.deploy( - sender, - code.into(), - value.unwrap_or(U256::zero()), + h160_to_b160(sender), + code.into_bytes().into(), + u256_to_ru256(value.unwrap_or(U256::zero())), None, ) { Ok(deploy_result) => TraceResult::from(deploy_result), @@ -192,10 +196,10 @@ impl CallArgs { let (tx, _) = builder.build(); let trace = TraceResult::from(executor.call_raw_committing( - sender, - tx.to_addr().copied().expect("an address to be here"), + h160_to_b160(sender), + h160_to_b160(tx.to_addr().copied().expect("an address to be here")), tx.data().cloned().unwrap_or_default().to_vec().into(), - tx.value().copied().unwrap_or_default(), + u256_to_ru256(tx.value().copied().unwrap_or_default()), )?); handle_traces(trace, &config, chain, labels, verbose, debug).await?; diff --git a/crates/cast/bin/cmd/run.rs b/crates/cast/bin/cmd/run.rs index 902271adf76bf..919195337b25a 100644 --- a/crates/cast/bin/cmd/run.rs +++ b/crates/cast/bin/cmd/run.rs @@ -12,7 +12,7 @@ use foundry_evm::{ executor::{inspector::cheatcodes::util::configure_tx_env, opts::EvmOpts, EvmError}, revm::primitives::U256 as rU256, trace::TracingExecutor, - utils::h256_to_b256, + utils::{h160_to_b160, h256_to_b256, u256_to_ru256}, }; use tracing::trace; @@ -117,12 +117,12 @@ impl RunArgs { let block = provider.get_block_with_txs(tx_block_number).await?; if let Some(ref block) = block { - env.block.timestamp = block.timestamp.into(); - env.block.coinbase = block.author.unwrap_or_default().into(); - env.block.difficulty = block.difficulty.into(); + env.block.timestamp = u256_to_ru256(block.timestamp); + env.block.coinbase = h160_to_b160(block.author.unwrap_or_default()); + env.block.difficulty = u256_to_ru256(block.difficulty); env.block.prevrandao = block.mix_hash.map(h256_to_b256); - env.block.basefee = block.base_fee_per_gas.unwrap_or_default().into(); - env.block.gas_limit = block.gas_limit.into(); + env.block.basefee = u256_to_ru256(block.base_fee_per_gas.unwrap_or_default()); + env.block.gas_limit = u256_to_ru256(block.gas_limit); } // Set the state to the moment right before the transaction diff --git a/crates/chisel/src/runner.rs b/crates/chisel/src/runner.rs index e03a76e11e721..72b888b4e984c 100644 --- a/crates/chisel/src/runner.rs +++ b/crates/chisel/src/runner.rs @@ -10,7 +10,9 @@ use ethers::{ use eyre::Result; use foundry_evm::{ executor::{DeployResult, Executor, RawCallResult}, + revm::primitives::U256 as rU256, trace::{CallTraceArena, TraceKind}, + utils::{b160_to_h160, h160_to_b160, u256_to_ru256}, }; use revm::interpreter::{return_ok, InstructionResult}; use std::collections::BTreeMap; @@ -92,17 +94,18 @@ impl ChiselRunner { /// contract. pub fn run(&mut self, bytecode: Bytes) -> Result<(Address, ChiselResult)> { // Set the sender's balance to [U256::MAX] for deployment of the REPL contract. - self.executor.set_balance(self.sender, U256::MAX)?; + self.executor.set_balance(h160_to_b160(self.sender), rU256::MAX)?; // Deploy an instance of the REPL contract // We don't care about deployment traces / logs here let DeployResult { address, .. } = self .executor - .deploy(self.sender, bytecode.0, 0.into(), None) + .deploy(h160_to_b160(self.sender), bytecode.0.into(), rU256::ZERO, None) .map_err(|err| eyre::eyre!("Failed to deploy REPL contract:\n{}", err))?; // Reset the sender's balance to the initial balance for calls. - self.executor.set_balance(self.sender, self.initial_balance)?; + self.executor + .set_balance(h160_to_b160(self.sender), u256_to_ru256(self.initial_balance))?; // Append the input to the `RUN_SELECTOR` to form the calldata let mut calldata = RUN_SELECTOR.to_vec(); @@ -111,9 +114,10 @@ impl ChiselRunner { } // Call the "run()" function of the REPL contract - let call_res = self.call(self.sender, address, Bytes::from(calldata), 0.into(), true); + let call_res = + self.call(self.sender, b160_to_h160(address), Bytes::from(calldata), 0.into(), true); - call_res.map(|res| (address, res)) + call_res.map(|res| (b160_to_h160(address), res)) } /// Executes the call @@ -140,7 +144,12 @@ impl ChiselRunner { false }; - let mut res = self.executor.call_raw(from, to, calldata.0.clone(), value)?; + let mut res = self.executor.call_raw( + h160_to_b160(from), + h160_to_b160(to), + calldata.0.clone().into(), + u256_to_ru256(value), + )?; let mut gas_used = res.gas_used; if matches!(res.exit_reason, return_ok!()) { // store the current gas limit and reset it later @@ -156,7 +165,12 @@ impl ChiselRunner { while (highest_gas_limit - lowest_gas_limit) > 1 { let mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2; self.executor.env.tx.gas_limit = mid_gas_limit; - let res = self.executor.call_raw(from, to, calldata.0.clone(), value)?; + let res = self.executor.call_raw( + h160_to_b160(from), + h160_to_b160(to), + calldata.0.clone().into(), + u256_to_ru256(value), + )?; match res.exit_reason { InstructionResult::Revert | InstructionResult::OutOfGas | @@ -191,18 +205,28 @@ impl ChiselRunner { cheatcodes.fs_commit = !cheatcodes.fs_commit; } - res = self.executor.call_raw(from, to, calldata.0.clone(), value)?; + res = self.executor.call_raw( + h160_to_b160(from), + h160_to_b160(to), + calldata.0.clone().into(), + u256_to_ru256(value), + )?; } if commit { // if explicitly requested we can now commit the call - res = self.executor.call_raw_committing(from, to, calldata.0, value)?; + res = self.executor.call_raw_committing( + h160_to_b160(from), + h160_to_b160(to), + calldata.0.clone().into(), + u256_to_ru256(value), + )?; } let RawCallResult { result, reverted, logs, traces, labels, chisel_state, .. } = res; Ok(ChiselResult { - returned: result, + returned: result.0, success: !reverted, gas_used, logs, @@ -214,7 +238,7 @@ impl ChiselRunner { vec![(TraceKind::Execution, traces)] }) .unwrap_or_default(), - labeled_addresses: labels, + labeled_addresses: labels.into_iter().map(|l| (b160_to_h160(l.0), l.1)).collect(), address: None, state: chisel_state, }) diff --git a/crates/debugger/src/debugger.rs b/crates/debugger/src/debugger.rs index 55ddcbd92a29e..16587c7616699 100644 --- a/crates/debugger/src/debugger.rs +++ b/crates/debugger/src/debugger.rs @@ -1,6 +1,6 @@ use crate::Ui; use foundry_common::{compile::ContractSources, evm::Breakpoints, get_contract_name}; -use foundry_evm::{debug::DebugArena, trace::CallTraceDecoder}; +use foundry_evm::{debug::DebugArena, trace::CallTraceDecoder, utils::b160_to_h160}; use tracing::trace; use crate::{TUIExitReason, Tui}; @@ -35,7 +35,7 @@ impl DebuggerArgs<'_> { .collect(); let tui = Tui::new( - flattened, + flattened.into_iter().map(|i| (b160_to_h160(i.0), i.1, i.2)).collect(), 0, identified_contracts, self.sources.clone(), diff --git a/crates/debugger/src/lib.rs b/crates/debugger/src/lib.rs index 7b25d2aa0d0b2..680b7af484219 100644 --- a/crates/debugger/src/lib.rs +++ b/crates/debugger/src/lib.rs @@ -875,7 +875,7 @@ Line::from(Span::styled("[t]: stack labels | [m]: memory decoding | [shift + j/k let min_len = format!("{:x}", max_i * 32).len(); // color memory words based on write/read - let mut word = None; + let mut word: Option = None; let mut color = None; if let Instruction::OpCode(op) = debug_steps[current_step].instruction { let stack_len = debug_steps[current_step].stack.len(); @@ -883,11 +883,11 @@ Line::from(Span::styled("[t]: stack labels | [m]: memory decoding | [shift + j/k let w = debug_steps[current_step].stack[stack_len - 1]; match op { opcode::MLOAD => { - word = Some(w.as_usize()); + word = Some(w.to()); color = Some(Color::Cyan); } opcode::MSTORE => { - word = Some(w.as_usize()); + word = Some(w.to()); color = Some(Color::Red); } _ => {} @@ -902,7 +902,7 @@ Line::from(Span::styled("[t]: stack labels | [m]: memory decoding | [shift + j/k if let Instruction::OpCode(op) = debug_steps[prev_step].instruction { if op == opcode::MSTORE { let prev_top = debug_steps[prev_step].stack[stack_len - 1]; - word = Some(prev_top.as_usize()); + word = Some(prev_top.to()); color = Some(Color::Green); } } diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index 257d849e3010f..a12497faa0481 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -49,6 +49,8 @@ revm = { workspace = true, default-features = false, features = [ "optional_no_base_fee", ] } +alloy-primitives = { workspace = true, default-features = false, features = ["std", "serde", "getrandom"] } + # Fuzzer proptest = "1" diff --git a/crates/evm/src/debug.rs b/crates/evm/src/debug.rs index c229dbca90b3e..6fa9c00dafe23 100644 --- a/crates/evm/src/debug.rs +++ b/crates/evm/src/debug.rs @@ -1,5 +1,5 @@ use crate::{abi::HEVM_ABI, CallKind}; -use ethers::types::{Address, U256}; +use alloy_primitives::{Address, U256}; use revm::interpreter::{Memory, OpCode}; use serde::{Deserialize, Serialize}; use std::fmt::Display; diff --git a/crates/evm/src/executor/abi/mod.rs b/crates/evm/src/executor/abi/mod.rs index 276fd27d917da..273c13502dc46 100644 --- a/crates/evm/src/executor/abi/mod.rs +++ b/crates/evm/src/executor/abi/mod.rs @@ -1,4 +1,6 @@ -use ethers::types::{Address, Selector, H160}; +//! Several ABI-related utilities for executors. + +use alloy_primitives::{Address, Selector}; pub use foundry_abi::{ console::{self, ConsoleEvents, CONSOLE_ABI}, hardhat_console::{self, HardhatConsoleCalls, HARDHATCONSOLE_ABI as HARDHAT_CONSOLE_ABI}, @@ -11,7 +13,7 @@ use std::collections::HashMap; /// /// This is the same address as the one used in DappTools's HEVM. /// `address(bytes20(uint160(uint256(keccak256('hevm cheat code')))))` -pub const CHEATCODE_ADDRESS: Address = H160([ +pub const CHEATCODE_ADDRESS: Address = Address::new([ 0x71, 0x09, 0x70, 0x9E, 0xcf, 0xa9, 0x1a, 0x80, 0x62, 0x6f, 0xf3, 0x98, 0x9d, 0x68, 0xf6, 0x7f, 0x5b, 0x1d, 0xd1, 0x2d, ]); @@ -19,7 +21,7 @@ pub const CHEATCODE_ADDRESS: Address = H160([ /// The Hardhat console address (0x000000000000000000636F6e736F6c652e6c6f67). /// /// See: https://github.com/nomiclabs/hardhat/blob/master/packages/hardhat-core/console.sol -pub const HARDHAT_CONSOLE_ADDRESS: Address = H160([ +pub const HARDHAT_CONSOLE_ADDRESS: Address = Address::new([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x2e, 0x6c, 0x6f, 0x67, ]); diff --git a/crates/evm/src/executor/backend/diagnostic.rs b/crates/evm/src/executor/backend/diagnostic.rs index 2baec89ecf97b..10fbb43d87ec4 100644 --- a/crates/evm/src/executor/backend/diagnostic.rs +++ b/crates/evm/src/executor/backend/diagnostic.rs @@ -1,8 +1,10 @@ use crate::{ executor::{backend::LocalForkId, inspector::Cheatcodes}, - Address, + utils::b160_to_h160, }; +use alloy_primitives::Address; use foundry_common::fmt::UIfmt; +use itertools::Itertools; /// Represents possible diagnostic cases on revert #[derive(Debug, Clone)] @@ -29,15 +31,18 @@ impl RevertDiagnostic { match self { RevertDiagnostic::ContractExistsOnOtherForks { contract, active, available_on } => { - let contract_label = get_label(contract); + let contract_label = get_label(&b160_to_h160(*contract)); format!( - r#"Contract {contract_label} does not exist on active fork with id `{active}` - But exists on non active forks: `{available_on:?}`"# + r#"Contract {} does not exist on active fork with id `{}` + But exists on non active forks: `[{}]`"#, + contract_label, + active, + available_on.iter().format(", ") ) } RevertDiagnostic::ContractDoesNotExist { contract, persistent, .. } => { - let contract_label = get_label(contract); + let contract_label = get_label(&b160_to_h160(*contract)); if *persistent { format!("Contract {contract_label} does not exist") } else { diff --git a/crates/evm/src/executor/backend/error.rs b/crates/evm/src/executor/backend/error.rs index d40dc06fb6481..f7bf27fcd1dc3 100644 --- a/crates/evm/src/executor/backend/error.rs +++ b/crates/evm/src/executor/backend/error.rs @@ -1,4 +1,5 @@ -use ethers::types::{Address, BlockId, H256, U256}; +use alloy_primitives::{Address, B256, U256}; +use ethers::types::BlockId; use foundry_utils::error::SolError; use futures::channel::mpsc::{SendError, TrySendError}; use std::{ @@ -16,7 +17,7 @@ pub enum DatabaseError { #[error("Failed to fetch AccountInfo {0:?}")] MissingAccount(Address), #[error("Could should already be loaded: {0:?}")] - MissingCode(H256), + MissingCode(B256), #[error(transparent)] Recv(#[from] RecvError), #[error(transparent)] @@ -34,9 +35,9 @@ pub enum DatabaseError { #[error("Block {0:?} does not exist")] BlockNotFound(BlockId), #[error("Failed to get transaction {0:?}: {1:?}")] - GetTransaction(H256, Arc), + GetTransaction(B256, Arc), #[error("Transaction {0:?} not found")] - TransactionNotFound(H256), + TransactionNotFound(B256), #[error( "CREATE2 Deployer (0x4e59b44847b379578588920ca78fbf26c0b4956c) not present on this chain.\n\nFor a production environment, you can deploy it using the pre-signed transaction from https://github.com/Arachnid/deterministic-deployment-proxy.\n\nFor a test environment, you can use vm.etch to place the required bytecode at that address." )] diff --git a/crates/evm/src/executor/backend/fuzz.rs b/crates/evm/src/executor/backend/fuzz.rs index b1c98bfbf2b2e..738fa8a34c2a7 100644 --- a/crates/evm/src/executor/backend/fuzz.rs +++ b/crates/evm/src/executor/backend/fuzz.rs @@ -1,18 +1,16 @@ -use crate::{ - executor::{ - backend::{ - diagnostic::RevertDiagnostic, error::DatabaseError, Backend, DatabaseExt, LocalForkId, - }, - fork::{CreateFork, ForkId}, - inspector::cheatcodes::Cheatcodes, +//! A wrapper around `Backend` that is clone-on-write used for fuzzing. + +use crate::executor::{ + backend::{ + diagnostic::RevertDiagnostic, error::DatabaseError, Backend, DatabaseExt, LocalForkId, }, - Address, + fork::{CreateFork, ForkId}, + inspector::cheatcodes::Cheatcodes, }; -use ethers::prelude::{H256, U256}; - +use alloy_primitives::{Address, B256, U256}; use revm::{ db::DatabaseRef, - primitives::{AccountInfo, Bytecode, Env, ResultAndState, B160, B256, U256 as rU256}, + primitives::{AccountInfo, Bytecode, Env, ResultAndState}, Database, Inspector, JournaledState, }; use std::borrow::Cow; @@ -129,7 +127,7 @@ impl<'a> DatabaseExt for FuzzBackendWrapper<'a> { fn create_fork_at_transaction( &mut self, fork: CreateFork, - transaction: H256, + transaction: B256, ) -> eyre::Result { trace!(?transaction, "fuzz: create fork at"); self.backend.to_mut().create_fork_at_transaction(fork, transaction) @@ -159,7 +157,7 @@ impl<'a> DatabaseExt for FuzzBackendWrapper<'a> { fn roll_fork_to_transaction( &mut self, id: Option, - transaction: H256, + transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { @@ -170,7 +168,7 @@ impl<'a> DatabaseExt for FuzzBackendWrapper<'a> { fn transact( &mut self, id: Option, - transaction: H256, + transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, cheatcodes_inspector: Option<&mut Cheatcodes>, @@ -231,7 +229,7 @@ impl<'a> DatabaseExt for FuzzBackendWrapper<'a> { impl<'a> DatabaseRef for FuzzBackendWrapper<'a> { type Error = DatabaseError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { DatabaseRef::basic(self.backend.as_ref(), address) } @@ -239,11 +237,11 @@ impl<'a> DatabaseRef for FuzzBackendWrapper<'a> { DatabaseRef::code_by_hash(self.backend.as_ref(), code_hash) } - fn storage(&self, address: B160, index: rU256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { DatabaseRef::storage(self.backend.as_ref(), address, index) } - fn block_hash(&self, number: rU256) -> Result { + fn block_hash(&self, number: U256) -> Result { DatabaseRef::block_hash(self.backend.as_ref(), number) } } @@ -251,7 +249,7 @@ impl<'a> DatabaseRef for FuzzBackendWrapper<'a> { impl<'a> Database for FuzzBackendWrapper<'a> { type Error = DatabaseError; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { DatabaseRef::basic(self, address) } @@ -259,11 +257,11 @@ impl<'a> Database for FuzzBackendWrapper<'a> { DatabaseRef::code_by_hash(self, code_hash) } - fn storage(&mut self, address: B160, index: rU256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { DatabaseRef::storage(self, address, index) } - fn block_hash(&mut self, number: rU256) -> Result { + fn block_hash(&mut self, number: U256) -> Result { DatabaseRef::block_hash(self, number) } } diff --git a/crates/evm/src/executor/backend/in_memory_db.rs b/crates/evm/src/executor/backend/in_memory_db.rs index 73373343497c8..4687db7804e95 100644 --- a/crates/evm/src/executor/backend/in_memory_db.rs +++ b/crates/evm/src/executor/backend/in_memory_db.rs @@ -1,8 +1,9 @@ //! The in memory DB use crate::executor::backend::error::DatabaseError; +use alloy_primitives::{Address, B256, U256}; use revm::{ db::{CacheDB, DatabaseRef, EmptyDB}, - primitives::{Account, AccountInfo, Bytecode, HashMap as Map, B160, B256, U256}, + primitives::{Account, AccountInfo, Bytecode, HashMap as Map}, Database, DatabaseCommit, }; @@ -30,7 +31,7 @@ impl Default for MemDb { impl DatabaseRef for MemDb { type Error = DatabaseError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { DatabaseRef::basic(&self.inner, address) } @@ -38,7 +39,7 @@ impl DatabaseRef for MemDb { DatabaseRef::code_by_hash(&self.inner, code_hash) } - fn storage(&self, address: B160, index: U256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { DatabaseRef::storage(&self.inner, address, index) } @@ -50,7 +51,7 @@ impl DatabaseRef for MemDb { impl Database for MemDb { type Error = DatabaseError; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { // Note: this will always return `Some(AccountInfo)`, See `EmptyDBWrapper` Database::basic(&mut self.inner, address) } @@ -59,7 +60,7 @@ impl Database for MemDb { Database::code_by_hash(&mut self.inner, code_hash) } - fn storage(&mut self, address: B160, index: U256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { Database::storage(&mut self.inner, address, index) } @@ -69,7 +70,7 @@ impl Database for MemDb { } impl DatabaseCommit for MemDb { - fn commit(&mut self, changes: Map) { + fn commit(&mut self, changes: Map) { DatabaseCommit::commit(&mut self.inner, changes) } } @@ -94,7 +95,7 @@ pub struct EmptyDBWrapper(EmptyDB); impl DatabaseRef for EmptyDBWrapper { type Error = DatabaseError; - fn basic(&self, _address: B160) -> Result, Self::Error> { + fn basic(&self, _address: Address) -> Result, Self::Error> { // Note: this will always return `Some(AccountInfo)`, for the reason explained above Ok(Some(AccountInfo::default())) } @@ -102,8 +103,7 @@ impl DatabaseRef for EmptyDBWrapper { fn code_by_hash(&self, code_hash: B256) -> Result { Ok(self.0.code_by_hash(code_hash)?) } - - fn storage(&self, address: B160, index: U256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { Ok(self.0.storage(address, index)?) } @@ -114,6 +114,8 @@ impl DatabaseRef for EmptyDBWrapper { #[cfg(test)] mod tests { + use alloy_primitives::b256; + use super::*; /// Ensures the `Database(Ref)` implementation for `revm::CacheDB` works as expected @@ -122,7 +124,7 @@ mod tests { #[test] fn cache_db_insert_basic_non_existing() { let mut db = CacheDB::new(EmptyDB::default()); - let address = B160::random(); + let address = Address::random(); // call `basic` on a non-existing account let info = Database::basic(&mut db, address).unwrap(); assert!(info.is_none()); @@ -142,7 +144,7 @@ mod tests { #[test] fn cache_db_insert_basic_default() { let mut db = CacheDB::new(EmptyDB::default()); - let address = B160::random(); + let address = Address::random(); let info = DatabaseRef::basic(&db, address).unwrap(); assert!(info.is_none()); @@ -161,7 +163,9 @@ mod tests { #[test] fn mem_db_insert_basic_default() { let mut db = MemDb::default(); - let address = B160::random(); + let address = Address::from_word(b256!( + "000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa96045" + )); let info = Database::basic(&mut db, address).unwrap(); assert!(info.is_some()); diff --git a/crates/evm/src/executor/backend/mod.rs b/crates/evm/src/executor/backend/mod.rs index 3e468f2235133..227e94eea5f08 100644 --- a/crates/evm/src/executor/backend/mod.rs +++ b/crates/evm/src/executor/backend/mod.rs @@ -1,3 +1,5 @@ +//! Foundry's main executor backend abstraction and implementation. + use crate::{ abi::CHEATCODE_ADDRESS, executor::{ @@ -6,12 +8,13 @@ use crate::{ inspector::{cheatcodes::Cheatcodes, DEFAULT_CREATE2_DEPLOYER}, snapshot::Snapshots, }, - utils::{b160_to_h160, h160_to_b160, h256_to_b256, ru256_to_u256, u256_to_ru256}, + utils::{b256_to_h256, h160_to_b160, h256_to_b256, ru256_to_u256, u256_to_ru256, u64_to_ru64}, CALLER, TEST_CONTRACT_ADDRESS, }; +use alloy_primitives::{b256, Address, B256, U256, U64}; use ethers::{ - prelude::{Block, H160, H256, U256}, - types::{Address, BlockNumber, Transaction, U64}, + prelude::Block, + types::{BlockNumber, Transaction}, utils::keccak256, }; pub use in_memory_db::MemDb; @@ -20,7 +23,7 @@ use revm::{ precompile::{Precompiles, SpecId}, primitives::{ Account, AccountInfo, Bytecode, CreateScheme, Env, HashMap as Map, Log, ResultAndState, - TransactTo, B160, B256, KECCAK_EMPTY, U256 as rU256, + TransactTo, KECCAK_EMPTY, }, Database, DatabaseCommit, Inspector, JournaledState, EVM, }; @@ -61,12 +64,13 @@ pub type LocalForkId = U256; type ForkLookupIndex = usize; /// All accounts that will have persistent storage across fork swaps. See also [`clone_data()`] -const DEFAULT_PERSISTENT_ACCOUNTS: [H160; 3] = +const DEFAULT_PERSISTENT_ACCOUNTS: [Address; 3] = [CHEATCODE_ADDRESS, DEFAULT_CREATE2_DEPLOYER, CALLER]; /// Slot corresponding to "failed" in bytes on the cheatcodes (HEVM) address. -const GLOBAL_FAILURE_SLOT: &str = - "0x6661696c65640000000000000000000000000000000000000000000000000000"; +/// Not prefixed with 0x. +const GLOBAL_FAILURE_SLOT: B256 = + b256!("6661696c65640000000000000000000000000000000000000000000000000000"); /// An extension trait that allows us to easily extend the `revm::Inspector` capabilities #[auto_impl::auto_impl(&mut, Box)] @@ -116,7 +120,7 @@ pub trait DatabaseExt: Database { fork: CreateFork, env: &mut Env, journaled_state: &mut JournaledState, - transaction: H256, + transaction: B256, ) -> eyre::Result { let id = self.create_fork_at_transaction(fork, transaction)?; self.select_fork(id, env, journaled_state)?; @@ -130,7 +134,7 @@ pub trait DatabaseExt: Database { fn create_fork_at_transaction( &mut self, fork: CreateFork, - transaction: H256, + transaction: B256, ) -> eyre::Result; /// Selects the fork's state @@ -175,7 +179,7 @@ pub trait DatabaseExt: Database { fn roll_fork_to_transaction( &mut self, id: Option, - transaction: H256, + transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, ) -> eyre::Result<()>; @@ -184,7 +188,7 @@ pub trait DatabaseExt: Database { fn transact( &mut self, id: Option, - transaction: H256, + transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, cheatcodes_inspector: Option<&mut Cheatcodes>, @@ -462,28 +466,28 @@ impl Backend { } } - pub fn insert_account_info(&mut self, address: H160, account: AccountInfo) { + pub fn insert_account_info(&mut self, address: Address, account: AccountInfo) { if let Some(db) = self.active_fork_db_mut() { - db.insert_account_info(h160_to_b160(address), account) + db.insert_account_info(address, account) } else { - self.mem_db.insert_account_info(h160_to_b160(address), account) + self.mem_db.insert_account_info(address, account) } } /// Inserts a value on an account's storage without overriding account info pub fn insert_account_storage( &mut self, - address: H160, + address: Address, slot: U256, value: U256, ) -> Result<(), DatabaseError> { let ret = if let Some(db) = self.active_fork_db_mut() { - db.insert_account_storage(h160_to_b160(address), slot.into(), value.into()) + db.insert_account_storage(address, slot, value) } else { - self.mem_db.insert_account_storage(h160_to_b160(address), slot.into(), value.into()) + self.mem_db.insert_account_storage(address, slot, value) }; - debug_assert!(self.storage(h160_to_b160(address), slot.into()).unwrap() == value.into()); + debug_assert!(self.storage(address, slot).unwrap() == value); ret } @@ -514,7 +518,7 @@ impl Backend { } /// Sets the caller address - pub fn set_caller(&mut self, acc: H160) -> &mut Self { + pub fn set_caller(&mut self, acc: Address) -> &mut Self { trace!(?acc, "setting caller account"); self.inner.caller = Some(acc); self.allow_cheatcode_access(acc); @@ -573,7 +577,7 @@ impl Backend { bool private _failed; } */ - let value = self.storage(h160_to_b160(address), U256::zero().into()).unwrap_or_default(); + let value = self.storage(address, U256::ZERO).unwrap_or_default(); value.as_le_bytes()[1] != 0 } @@ -588,7 +592,6 @@ impl Backend { address: Address, current_state: &JournaledState, ) -> bool { - let address = h160_to_b160(address); if let Some(account) = current_state.state.get(&address) { let value = account .storage @@ -606,10 +609,9 @@ impl Backend { /// in "failed" /// See pub fn is_global_failure(&self, current_state: &JournaledState) -> bool { - let index: rU256 = - U256::from_str_radix(GLOBAL_FAILURE_SLOT, 16).expect("This is a bug.").into(); - if let Some(account) = current_state.state.get(&h160_to_b160(CHEATCODE_ADDRESS)) { - let value = account.storage.get(&index).cloned().unwrap_or_default().present_value(); + if let Some(account) = current_state.state.get(&CHEATCODE_ADDRESS) { + let slot: U256 = GLOBAL_FAILURE_SLOT.into(); + let value = account.storage.get(&slot).cloned().unwrap_or_default().present_value(); return value == revm::primitives::U256::from(1) } @@ -722,7 +724,7 @@ impl Backend { /// /// We need to track these mainly to prevent issues when switching between different evms pub(crate) fn initialize(&mut self, env: &Env) { - self.set_caller(b160_to_h160(env.tx.caller)); + self.set_caller(env.tx.caller); self.set_spec_id(SpecId::from_spec_id(env.cfg.spec_id)); let test_contract = match env.tx.transact_to { @@ -731,11 +733,11 @@ impl Backend { revm::primitives::create_address(env.tx.caller, env.tx.nonce.unwrap_or_default()) } TransactTo::Create(CreateScheme::Create2 { salt }) => { - let code_hash = H256::from_slice(keccak256(&env.tx.data).as_slice()); - revm::primitives::create2_address(env.tx.caller, h256_to_b256(code_hash), salt) + let code_hash = B256::from_slice(keccak256(&env.tx.data).as_slice()); + revm::primitives::create2_address(env.tx.caller, code_hash, salt) } }; - self.set_test_contract(b160_to_h160(test_contract)); + self.set_test_contract(test_contract); } /// Executes the configured test call of the `env` without committing state changes @@ -756,7 +758,7 @@ impl Backend { } /// Returns true if the address is a precompile - pub fn is_existing_precompile(&self, addr: &B160) -> bool { + pub fn is_existing_precompile(&self, addr: &Address) -> bool { self.inner.precompiles().contains(addr) } @@ -774,9 +776,7 @@ impl Backend { .fork_init_journaled_state .state .iter() - .filter(|(addr, _)| { - !self.is_existing_precompile(addr) && !self.is_persistent(&b160_to_h160(**addr)) - }) + .filter(|(addr, _)| !self.is_existing_precompile(addr) && !self.is_persistent(addr)) .map(|(addr, _)| addr) .copied() .collect::>(); @@ -786,7 +786,7 @@ impl Backend { for loaded_account in loaded_accounts.iter().copied() { trace!(?loaded_account, "replacing account on init"); let fork_account = Database::basic(&mut fork.db, loaded_account)? - .ok_or(DatabaseError::MissingAccount(b160_to_h160(loaded_account)))?; + .ok_or(DatabaseError::MissingAccount(loaded_account))?; let init_account = journaled_state.state.get_mut(&loaded_account).expect("exists; qed"); init_account.info = fork_account; @@ -800,7 +800,7 @@ impl Backend { fn get_block_number_and_block_for_transaction( &self, id: LocalForkId, - transaction: H256, + transaction: B256, ) -> eyre::Result<(U64, Block)> { let fork = self.inner.get_fork_by_id(id)?; let tx = fork.db.db.get_transaction(transaction)?; @@ -812,7 +812,7 @@ impl Backend { // we need to subtract 1 here because we want the state before the transaction // was mined let fork_block = tx_block - 1; - Ok((fork_block, block)) + Ok((U64::from(fork_block.as_u64()), block)) } else { let block = fork.db.db.get_full_block(BlockNumber::Latest)?; @@ -820,7 +820,7 @@ impl Backend { .number .ok_or_else(|| DatabaseError::BlockNotFound(BlockNumber::Latest.into()))?; - Ok((number, block)) + Ok((U64::from(number.as_u64()), block)) } } @@ -831,7 +831,7 @@ impl Backend { &mut self, id: LocalForkId, env: Env, - tx_hash: H256, + tx_hash: B256, journaled_state: &mut JournaledState, ) -> eyre::Result> { trace!(?id, ?tx_hash, "replay until transaction"); @@ -845,7 +845,7 @@ impl Backend { .get_full_block(BlockNumber::Number(ru256_to_u256(env.block.number).as_u64().into()))?; for tx in full_block.transactions.into_iter() { - if tx.hash().eq(&tx_hash) { + if tx.hash().eq(&b256_to_h256(tx_hash)) { // found the target transaction return Ok(Some(tx)) } @@ -941,7 +941,7 @@ impl DatabaseExt for Backend { fn create_fork_at_transaction( &mut self, fork: CreateFork, - transaction: H256, + transaction: B256, ) -> eyre::Result { trace!(?transaction, "create fork at transaction"); let id = self.create_fork(fork)?; @@ -962,6 +962,7 @@ impl DatabaseExt for Backend { Ok(id) } + /// Select an existing fork by id. /// When switching forks we copy the shared state fn select_fork( &mut self, @@ -996,7 +997,7 @@ impl DatabaseExt for Backend { // Initialize caller with its fork info if let Some(mut acc) = caller_account { let fork_account = Database::basic(&mut target_fork.db, caller)? - .ok_or(DatabaseError::MissingAccount(b160_to_h160(caller)))?; + .ok_or(DatabaseError::MissingAccount(caller))?; acc.info = fork_account; target_fork.journaled_state.state.insert(caller, acc); @@ -1068,7 +1069,7 @@ impl DatabaseExt for Backend { trace!(?id, ?block_number, "roll fork"); let id = self.ensure_fork(id)?; let (fork_id, backend, fork_env) = - self.forks.roll_fork(self.inner.ensure_fork_id(id).cloned()?, block_number.as_u64())?; + self.forks.roll_fork(self.inner.ensure_fork_id(id).cloned()?, block_number.to())?; // this will update the local mapping self.inner.roll_fork(id, fork_id, backend)?; @@ -1101,7 +1102,7 @@ impl DatabaseExt for Backend { for (addr, acc) in journaled_state.state.iter() { if acc.is_touched() { merge_journaled_state_data( - b160_to_h160(*addr), + *addr, journaled_state, &mut active.journaled_state, ); @@ -1119,7 +1120,7 @@ impl DatabaseExt for Backend { fn roll_fork_to_transaction( &mut self, id: Option, - transaction: H256, + transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { @@ -1130,16 +1131,16 @@ impl DatabaseExt for Backend { self.get_block_number_and_block_for_transaction(id, transaction)?; // roll the fork to the transaction's block or latest if it's pending - self.roll_fork(Some(id), fork_block.as_u64().into(), env, journaled_state)?; + self.roll_fork(Some(id), fork_block.to(), env, journaled_state)?; // update the block's env accordingly - env.block.timestamp = block.timestamp.into(); + env.block.timestamp = u256_to_ru256(block.timestamp); env.block.coinbase = h160_to_b160(block.author.unwrap_or_default()); - env.block.difficulty = block.difficulty.into(); + env.block.difficulty = u256_to_ru256(block.difficulty); env.block.prevrandao = block.mix_hash.map(h256_to_b256); - env.block.basefee = block.base_fee_per_gas.unwrap_or_default().into(); - env.block.gas_limit = block.gas_limit.into(); - env.block.number = u256_to_ru256(block.number.unwrap_or(fork_block).as_u64().into()); + env.block.basefee = u256_to_ru256(block.base_fee_per_gas.unwrap_or_default()); + env.block.gas_limit = u256_to_ru256(block.gas_limit); + env.block.number = block.number.map(u64_to_ru64).unwrap_or(fork_block).to(); // replay all transactions that came before let env = env.clone(); @@ -1152,7 +1153,7 @@ impl DatabaseExt for Backend { fn transact( &mut self, maybe_id: Option, - transaction: H256, + transaction: B256, env: &mut Env, journaled_state: &mut JournaledState, cheatcodes_inspector: Option<&mut Cheatcodes>, @@ -1279,7 +1280,7 @@ impl DatabaseExt for Backend { impl DatabaseRef for Backend { type Error = DatabaseError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { if let Some(db) = self.active_fork_db() { db.basic(address) } else { @@ -1295,7 +1296,7 @@ impl DatabaseRef for Backend { } } - fn storage(&self, address: B160, index: rU256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { if let Some(db) = self.active_fork_db() { DatabaseRef::storage(db, address, index) } else { @@ -1303,7 +1304,7 @@ impl DatabaseRef for Backend { } } - fn block_hash(&self, number: rU256) -> Result { + fn block_hash(&self, number: U256) -> Result { if let Some(db) = self.active_fork_db() { db.block_hash(number) } else { @@ -1314,7 +1315,7 @@ impl DatabaseRef for Backend { impl<'a> DatabaseRef for &'a mut Backend { type Error = DatabaseError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { if let Some(db) = self.active_fork_db() { DatabaseRef::basic(db, address) } else { @@ -1330,7 +1331,7 @@ impl<'a> DatabaseRef for &'a mut Backend { } } - fn storage(&self, address: B160, index: rU256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { if let Some(db) = self.active_fork_db() { DatabaseRef::storage(db, address, index) } else { @@ -1338,7 +1339,7 @@ impl<'a> DatabaseRef for &'a mut Backend { } } - fn block_hash(&self, number: rU256) -> Result { + fn block_hash(&self, number: U256) -> Result { if let Some(db) = self.active_fork_db() { DatabaseRef::block_hash(db, number) } else { @@ -1348,7 +1349,7 @@ impl<'a> DatabaseRef for &'a mut Backend { } impl DatabaseCommit for Backend { - fn commit(&mut self, changes: Map) { + fn commit(&mut self, changes: Map) { if let Some(db) = self.active_fork_db_mut() { db.commit(changes) } else { @@ -1359,7 +1360,7 @@ impl DatabaseCommit for Backend { impl Database for Backend { type Error = DatabaseError; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { if let Some(db) = self.active_fork_db_mut() { db.basic(address) } else { @@ -1375,7 +1376,7 @@ impl Database for Backend { } } - fn storage(&mut self, address: B160, index: rU256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { if let Some(db) = self.active_fork_db_mut() { Database::storage(db, address, index) } else { @@ -1383,7 +1384,7 @@ impl Database for Backend { } } - fn block_hash(&mut self, number: rU256) -> Result { + fn block_hash(&mut self, number: U256) -> Result { if let Some(db) = self.active_fork_db_mut() { db.block_hash(number) } else { @@ -1413,7 +1414,7 @@ pub struct Fork { impl Fork { /// Returns true if the account is a contract pub fn is_contract(&self, acc: Address) -> bool { - if let Ok(Some(acc)) = self.db.basic(h160_to_b160(acc)) { + if let Ok(Some(acc)) = self.db.basic(acc) { if acc.code_hash != KECCAK_EMPTY { return true } @@ -1624,7 +1625,7 @@ impl BackendInner { fn next_id(&mut self) -> U256 { let id = self.next_fork_id; - self.next_fork_id += U256::one(); + self.next_fork_id += U256::from(1); id } @@ -1707,8 +1708,6 @@ fn merge_journaled_state_data( active_journaled_state: &JournaledState, fork_journaled_state: &mut JournaledState, ) { - let addr = h160_to_b160(addr); - if let Some(mut acc) = active_journaled_state.state.get(&addr).cloned() { trace!(?addr, "updating journaled_state account data"); if let Some(fork_account) = fork_journaled_state.state.get_mut(&addr) { @@ -1729,8 +1728,6 @@ fn merge_db_account_data( ) { trace!(?addr, "merging database data"); - let addr = h160_to_b160(addr); - let mut acc = if let Some(acc) = active.accounts.get(&addr).cloned() { acc } else { @@ -1754,8 +1751,6 @@ fn merge_db_account_data( /// Returns true of the address is a contract fn is_contract_in_state(journaled_state: &JournaledState, acc: Address) -> bool { - let acc = h160_to_b160(acc); - journaled_state .state .get(&acc) diff --git a/crates/evm/src/executor/backend/snapshot.rs b/crates/evm/src/executor/backend/snapshot.rs index 36f1aa611788c..73ec8c5d7df76 100644 --- a/crates/evm/src/executor/backend/snapshot.rs +++ b/crates/evm/src/executor/backend/snapshot.rs @@ -1,5 +1,6 @@ +use alloy_primitives::{Address, B256, U256}; use revm::{ - primitives::{AccountInfo, Env, HashMap as Map, B160, B256, U256}, + primitives::{AccountInfo, Env, HashMap as Map}, JournaledState, }; use serde::{Deserialize, Serialize}; @@ -7,8 +8,8 @@ use serde::{Deserialize, Serialize}; /// A minimal abstraction of a state at a certain point in time #[derive(Default, Clone, Debug, Serialize, Deserialize)] pub struct StateSnapshot { - pub accounts: Map, - pub storage: Map>, + pub accounts: Map, + pub storage: Map>, pub block_hashes: Map, } diff --git a/crates/evm/src/executor/builder.rs b/crates/evm/src/executor/builder.rs index 9369bc4f2a0a2..5cbf6e453d650 100644 --- a/crates/evm/src/executor/builder.rs +++ b/crates/evm/src/executor/builder.rs @@ -1,6 +1,6 @@ use super::{inspector::InspectorStackBuilder, Executor}; use crate::executor::backend::Backend; -use ethers::types::U256; +use alloy_primitives::U256; use revm::primitives::{Env, SpecId}; /// The builder that allows to configure an evm [`Executor`] which a stack of optional @@ -67,8 +67,8 @@ impl ExecutorBuilder { let Self { mut stack, gas_limit, spec_id } = self; env.cfg.spec_id = spec_id; stack.block = Some(env.block.clone()); - stack.gas_price = Some(env.tx.gas_price.into()); - let gas_limit = gas_limit.unwrap_or(env.block.gas_limit.into()); + stack.gas_price = Some(env.tx.gas_price); + let gas_limit = gas_limit.unwrap_or(env.block.gas_limit); Executor::new(db, env, stack.build(), gas_limit) } } diff --git a/crates/evm/src/executor/fork/backend.rs b/crates/evm/src/executor/fork/backend.rs index e8b458248b806..ade1e6382363a 100644 --- a/crates/evm/src/executor/fork/backend.rs +++ b/crates/evm/src/executor/fork/backend.rs @@ -4,12 +4,13 @@ use crate::{ backend::error::{DatabaseError, DatabaseResult}, fork::{cache::FlushJsonBlockCacheDB, BlockchainDb}, }, - utils::{b160_to_h160, b256_to_h256, h160_to_b160, h256_to_b256, ru256_to_u256, u256_to_ru256}, + utils::{b160_to_h160, b256_to_h256, h256_to_b256, u256_to_ru256}, }; +use alloy_primitives::{Address, Bytes, B256, U256}; use ethers::{ core::abi::ethereum_types::BigEndianHash, providers::Middleware, - types::{Address, Block, BlockId, Bytes, Transaction, H256, U256}, + types::{Block, BlockId, NameOrAddress, Transaction}, utils::keccak256, }; use foundry_common::NON_ARCHIVE_NODE_WARNING; @@ -21,7 +22,7 @@ use futures::{ }; use revm::{ db::DatabaseRef, - primitives::{AccountInfo, Bytecode, B160, B256, KECCAK_EMPTY, U256 as rU256}, + primitives::{AccountInfo, Bytecode, KECCAK_EMPTY}, }; use std::{ collections::{hash_map::Entry, HashMap, VecDeque}, @@ -37,7 +38,7 @@ use std::{ type AccountFuture = Pin, Address)> + Send>>; type StorageFuture = Pin, Address, U256)> + Send>>; -type BlockHashFuture = Pin, u64)> + Send>>; +type BlockHashFuture = Pin, u64)> + Send>>; type FullBlockFuture = Pin< Box< dyn Future>, Err>, BlockId)> @@ -45,12 +46,12 @@ type FullBlockFuture = Pin< >, >; type TransactionFuture = Pin< - Box, Err>, H256)> + Send>, + Box, Err>, B256)> + Send>, >; type AccountInfoSender = OneshotSender>; type StorageSender = OneshotSender>; -type BlockHashSender = OneshotSender>; +type BlockHashSender = OneshotSender>; type FullBlockSender = OneshotSender>>; type TransactionSender = OneshotSender>; @@ -75,7 +76,7 @@ enum BackendRequest { /// Fetch an entire block with transactions FullBlock(BlockId, FullBlockSender), /// Fetch a transaction - Transaction(H256, TransactionSender), + Transaction(B256, TransactionSender), /// Sets the pinned block to fetch data from SetPinnedBlock(BlockId), } @@ -139,7 +140,7 @@ where match req { BackendRequest::Basic(addr, sender) => { trace!(target: "backendhandler", "received request basic address={:?}", addr); - let acc = self.db.accounts().read().get(&h160_to_b160(addr)).cloned(); + let acc = self.db.accounts().read().get(&addr).cloned(); if let Some(basic) = acc { let _ = sender.send(Ok(basic)); } else { @@ -147,9 +148,9 @@ where } } BackendRequest::BlockHash(number, sender) => { - let hash = self.db.block_hashes().read().get(&rU256::from(number)).cloned(); + let hash = self.db.block_hashes().read().get(&U256::from(number)).cloned(); if let Some(hash) = hash { - let _ = sender.send(Ok(hash.into())); + let _ = sender.send(Ok(hash)); } else { self.request_hash(number, sender); } @@ -162,14 +163,10 @@ where } BackendRequest::Storage(addr, idx, sender) => { // account is already stored in the cache - let value = self - .db - .storage() - .read() - .get(&h160_to_b160(addr)) - .and_then(|acc| acc.get(&u256_to_ru256(idx)).copied()); + let value = + self.db.storage().read().get(&addr).and_then(|acc| acc.get(&idx).copied()); if let Some(value) = value { - let _ = sender.send(Ok(ru256_to_u256(value))); + let _ = sender.send(Ok(value)); } else { // account present but not storage -> fetch storage self.request_account_storage(addr, idx, sender); @@ -194,9 +191,15 @@ where let block_id = self.block_id; let fut = Box::pin(async move { // serialize & deserialize back to U256 - let idx_req = H256::from_uint(&idx); - let storage = provider.get_storage_at(address, idx_req, block_id).await; - let storage = storage.map(|storage| storage.into_uint()); + let idx_req = B256::from(idx); + let storage = provider + .get_storage_at( + NameOrAddress::Address(b160_to_h160(address)), + b256_to_h256(idx_req), + block_id, + ) + .await; + let storage = storage.map(|storage| storage.into_uint()).map(u256_to_ru256); (storage, address, idx) }); self.pending_requests.push(ProviderRequest::Storage(fut)); @@ -210,10 +213,14 @@ where let provider = self.provider.clone(); let block_id = self.block_id; let fut = Box::pin(async move { - let balance = provider.get_balance(address, block_id); - let nonce = provider.get_transaction_count(address, block_id); - let code = provider.get_code(address, block_id); - let resp = tokio::try_join!(balance, nonce, code); + let balance = + provider.get_balance(NameOrAddress::Address(b160_to_h160(address)), block_id); + let nonce = provider + .get_transaction_count(NameOrAddress::Address(b160_to_h160(address)), block_id); + let code = provider.get_code(NameOrAddress::Address(b160_to_h160(address)), block_id); + let resp = tokio::try_join!(balance, nonce, code).map(|(balance, nonce, code)| { + (u256_to_ru256(balance), u256_to_ru256(nonce), Bytes::from(code.0)) + }); (resp, address) }); ProviderRequest::Account(fut) @@ -244,10 +251,10 @@ where } /// process a request for a transactions - fn request_transaction(&mut self, tx: H256, sender: TransactionSender) { + fn request_transaction(&mut self, tx: B256, sender: TransactionSender) { let provider = self.provider.clone(); let fut = Box::pin(async move { - let block = provider.get_transaction(tx).await; + let block = provider.get_transaction(b256_to_h256(tx)).await; (sender, block, tx) }); @@ -282,7 +289,7 @@ where Err(err) } }; - (block_hash, number) + (block_hash.map(h256_to_b256), number) }); self.pending_requests.push(ProviderRequest::BlockHash(fut)); } @@ -350,12 +357,14 @@ where // update the cache let acc = AccountInfo { - nonce: nonce.as_u64(), - balance: balance.into(), - code: code.map(|bytes| Bytecode::new_raw(bytes).to_checked()), + nonce: nonce.to(), + balance, + code: code.map(|bytes| { + Bytecode::new_raw(alloy_primitives::Bytes(bytes)).to_checked() + }), code_hash, }; - pin.db.accounts().write().insert(addr.into(), acc.clone()); + pin.db.accounts().write().insert(addr, acc.clone()); // notify all listeners if let Some(listeners) = pin.account_requests.remove(&addr) { @@ -389,12 +398,7 @@ where }; // update the cache - pin.db - .storage() - .write() - .entry(addr.into()) - .or_default() - .insert(idx.into(), value.into()); + pin.db.storage().write().entry(addr).or_default().insert(idx, value); // notify all listeners if let Some(listeners) = pin.storage_requests.remove(&(addr, idx)) { @@ -425,7 +429,7 @@ where }; // update the cache - pin.db.block_hashes().write().insert(rU256::from(number), value.into()); + pin.db.block_hashes().write().insert(U256::from(number), value); // notify all listeners if let Some(listeners) = pin.block_requests.remove(&number) { @@ -598,7 +602,7 @@ impl SharedBackend { } /// Returns the transaction for the hash - pub fn get_transaction(&self, tx: H256) -> DatabaseResult { + pub fn get_transaction(&self, tx: B256) -> DatabaseResult { tokio::task::block_in_place(|| { let (sender, rx) = oneshot_channel(); let req = BackendRequest::Transaction(tx, sender); @@ -625,7 +629,7 @@ impl SharedBackend { }) } - fn do_get_block_hash(&self, number: u64) -> DatabaseResult { + fn do_get_block_hash(&self, number: u64) -> DatabaseResult { tokio::task::block_in_place(|| { let (sender, rx) = oneshot_channel(); let req = BackendRequest::BlockHash(number, sender); @@ -643,9 +647,9 @@ impl SharedBackend { impl DatabaseRef for SharedBackend { type Error = DatabaseError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { trace!( target: "sharedbackend", "request basic {:?}", address); - self.do_get_basic(b160_to_h160(address)).map_err(|err| { + self.do_get_basic(address).map_err(|err| { error!(target: "sharedbackend", ?err, ?address, "Failed to send/recv `basic`"); if err.is_possibly_non_archive_node_error() { error!(target: "sharedbackend", "{NON_ARCHIVE_NODE_WARNING}"); @@ -655,29 +659,29 @@ impl DatabaseRef for SharedBackend { } fn code_by_hash(&self, hash: B256) -> Result { - Err(DatabaseError::MissingCode(b256_to_h256(hash))) + Err(DatabaseError::MissingCode(hash)) } - fn storage(&self, address: B160, index: rU256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { trace!( target: "sharedbackend", "request storage {:?} at {:?}", address, index); - match self.do_get_storage(b160_to_h160(address), index.into()).map_err(|err| { + match self.do_get_storage(address, index).map_err(|err| { error!( target: "sharedbackend", ?err, ?address, ?index, "Failed to send/recv `storage`"); if err.is_possibly_non_archive_node_error() { error!(target: "sharedbackend", "{NON_ARCHIVE_NODE_WARNING}"); } err }) { - Ok(val) => Ok(val.into()), + Ok(val) => Ok(val), Err(err) => Err(err), } } - fn block_hash(&self, number: rU256) -> Result { - if number > rU256::from(u64::MAX) { + fn block_hash(&self, number: U256) -> Result { + if number > U256::from(u64::MAX) { return Ok(KECCAK_EMPTY) } - let number: U256 = number.into(); - let number = number.as_u64(); + let number: U256 = number; + let number = number.to(); trace!( target: "sharedbackend", "request block hash for number {:?}", number); match self.do_get_block_hash(number).map_err(|err| { error!(target: "sharedbackend",?err, ?number, "Failed to send/recv `block_hash`"); @@ -686,7 +690,7 @@ impl DatabaseRef for SharedBackend { } err }) { - Ok(val) => Ok(h256_to_b256(val)), + Ok(val) => Ok(val), Err(err) => Err(err), } } @@ -719,9 +723,9 @@ mod tests { let backend = SharedBackend::spawn_backend(Arc::new(provider), db.clone(), None).await; // some rng contract from etherscan - let address: B160 = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); + let address: Address = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); - let idx = rU256::from(0u64); + let idx = U256::from(0u64); let value = backend.storage(address, idx).unwrap(); let account = backend.basic(address).unwrap().unwrap(); @@ -732,7 +736,7 @@ mod tests { assert_eq!(slots.len(), 1); assert_eq!(slots.get(&idx).copied().unwrap(), value); - let num = rU256::from(10u64); + let num = U256::from(10u64); let hash = backend.block_hash(num).unwrap(); let mem_hash = *db.block_hashes().read().get(&num).unwrap(); assert_eq!(hash, mem_hash); @@ -740,7 +744,7 @@ mod tests { let max_slots = 5; let handle = std::thread::spawn(move || { for i in 1..max_slots { - let idx = rU256::from(i); + let idx = U256::from(i); let _ = backend.storage(address, idx); } }); @@ -778,16 +782,16 @@ mod tests { let backend = Backend::spawn(Some(fork)).await; // some rng contract from etherscan - let address: B160 = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); + let address: Address = "63091244180ae240c87d1f528f5f269134cb07b3".parse().unwrap(); - let idx = rU256::from(0u64); + let idx = U256::from(0u64); let _value = backend.storage(address, idx); let _account = backend.basic(address); // fill some slots let num_slots = 10u64; for idx in 1..num_slots { - let _ = backend.storage(address, rU256::from(idx)); + let _ = backend.storage(address, U256::from(idx)); } drop(backend); diff --git a/crates/evm/src/executor/fork/cache.rs b/crates/evm/src/executor/fork/cache.rs index 12d04869ce531..f9a96772ce34d 100644 --- a/crates/evm/src/executor/fork/cache.rs +++ b/crates/evm/src/executor/fork/cache.rs @@ -1,10 +1,9 @@ //! Cache related abstraction use crate::executor::backend::snapshot::StateSnapshot; +use alloy_primitives::{Address, B256, U256}; use parking_lot::RwLock; use revm::{ - primitives::{ - Account, AccountInfo, AccountStatus, HashMap as Map, B160, B256, KECCAK_EMPTY, U256, - }, + primitives::{Account, AccountInfo, AccountStatus, HashMap as Map, KECCAK_EMPTY}, DatabaseCommit, }; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; @@ -87,12 +86,12 @@ impl BlockchainDb { } /// Returns the map that holds the account related info - pub fn accounts(&self) -> &RwLock> { + pub fn accounts(&self) -> &RwLock> { &self.db.accounts } /// Returns the map that holds the storage related info - pub fn storage(&self) -> &RwLock> { + pub fn storage(&self) -> &RwLock> { &self.db.storage } @@ -232,9 +231,9 @@ impl<'de> Deserialize<'de> for BlockchainDbMeta { #[derive(Debug, Default)] pub struct MemDb { /// Account related data - pub accounts: RwLock>, + pub accounts: RwLock>, /// Storage related data - pub storage: RwLock>, + pub storage: RwLock>, /// All retrieved block hashes pub block_hashes: RwLock>, } @@ -248,12 +247,12 @@ impl MemDb { } // Inserts the account, replacing it if it exists already - pub fn do_insert_account(&self, address: B160, account: AccountInfo) { + pub fn do_insert_account(&self, address: Address, account: AccountInfo) { self.accounts.write().insert(address, account); } /// The implementation of [DatabaseCommit::commit()] - pub fn do_commit(&self, changes: Map) { + pub fn do_commit(&self, changes: Map) { let mut storage = self.storage.write(); let mut accounts = self.accounts.write(); for (add, mut acc) in changes { @@ -305,7 +304,7 @@ impl Clone for MemDb { } impl DatabaseCommit for MemDb { - fn commit(&mut self, changes: Map) { + fn commit(&mut self, changes: Map) { self.do_commit(changes) } } diff --git a/crates/evm/src/executor/fork/database.rs b/crates/evm/src/executor/fork/database.rs index c9b58c839de89..8da324b24cf29 100644 --- a/crates/evm/src/executor/fork/database.rs +++ b/crates/evm/src/executor/fork/database.rs @@ -8,11 +8,12 @@ use crate::{ }, revm::db::CacheDB, }; -use ethers::{prelude::U256, types::BlockId}; +use alloy_primitives::{Address, B256, U256}; +use ethers::types::BlockId; use parking_lot::Mutex; use revm::{ db::DatabaseRef, - primitives::{Account, AccountInfo, Bytecode, HashMap as Map, B160, B256, U256 as rU256}, + primitives::{Account, AccountInfo, Bytecode, HashMap as Map}, Database, DatabaseCommit, }; use std::sync::Arc; @@ -151,7 +152,7 @@ impl ForkedDatabase { impl Database for ForkedDatabase { type Error = DatabaseError; - fn basic(&mut self, address: B160) -> Result, Self::Error> { + fn basic(&mut self, address: Address) -> Result, Self::Error> { // Note: this will always return Some, since the `SharedBackend` will always load the // account, this differs from `::basic`, See also // [MemDb::ensure_loaded](crate::executor::backend::MemDb::ensure_loaded) @@ -162,11 +163,11 @@ impl Database for ForkedDatabase { Database::code_by_hash(&mut self.cache_db, code_hash) } - fn storage(&mut self, address: B160, index: rU256) -> Result { + fn storage(&mut self, address: Address, index: U256) -> Result { Database::storage(&mut self.cache_db, address, index) } - fn block_hash(&mut self, number: rU256) -> Result { + fn block_hash(&mut self, number: U256) -> Result { Database::block_hash(&mut self.cache_db, number) } } @@ -174,7 +175,7 @@ impl Database for ForkedDatabase { impl DatabaseRef for ForkedDatabase { type Error = DatabaseError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { self.cache_db.basic(address) } @@ -182,17 +183,17 @@ impl DatabaseRef for ForkedDatabase { self.cache_db.code_by_hash(code_hash) } - fn storage(&self, address: B160, index: rU256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { DatabaseRef::storage(&self.cache_db, address, index) } - fn block_hash(&self, number: rU256) -> Result { + fn block_hash(&self, number: U256) -> Result { self.cache_db.block_hash(number) } } impl DatabaseCommit for ForkedDatabase { - fn commit(&mut self, changes: Map) { + fn commit(&mut self, changes: Map) { self.database_mut().commit(changes) } } @@ -209,7 +210,7 @@ pub struct ForkDbSnapshot { // === impl DbSnapshot === impl ForkDbSnapshot { - fn get_storage(&self, address: B160, index: rU256) -> Option { + fn get_storage(&self, address: Address, index: U256) -> Option { self.local.accounts.get(&address).and_then(|account| account.storage.get(&index)).copied() } } @@ -220,7 +221,7 @@ impl ForkDbSnapshot { impl DatabaseRef for ForkDbSnapshot { type Error = DatabaseError; - fn basic(&self, address: B160) -> Result, Self::Error> { + fn basic(&self, address: Address) -> Result, Self::Error> { match self.local.accounts.get(&address) { Some(account) => Ok(Some(account.info.clone())), None => { @@ -238,7 +239,7 @@ impl DatabaseRef for ForkDbSnapshot { self.local.code_by_hash(code_hash) } - fn storage(&self, address: B160, index: rU256) -> Result { + fn storage(&self, address: Address, index: U256) -> Result { match self.local.accounts.get(&address) { Some(account) => match account.storage.get(&index) { Some(entry) => Ok(*entry), @@ -254,7 +255,7 @@ impl DatabaseRef for ForkDbSnapshot { } } - fn block_hash(&self, number: rU256) -> Result { + fn block_hash(&self, number: U256) -> Result { match self.snapshot.block_hashes.get(&number).copied() { None => self.local.block_hash(number), Some(block_hash) => Ok(block_hash), @@ -285,12 +286,12 @@ mod tests { let backend = SharedBackend::spawn_backend(Arc::new(provider), db.clone(), None).await; let mut db = ForkedDatabase::new(backend, db); - let address = B160::random(); + let address = Address::random(); let info = Database::basic(&mut db, address).unwrap(); assert!(info.is_some()); let mut info = info.unwrap(); - info.balance = rU256::from(500u64); + info.balance = U256::from(500u64); // insert the modified account info db.database_mut().insert_account_info(address, info.clone()); diff --git a/crates/evm/src/executor/fork/init.rs b/crates/evm/src/executor/fork/init.rs index 0c42b3e03bb3a..539e4f888d505 100644 --- a/crates/evm/src/executor/fork/init.rs +++ b/crates/evm/src/executor/fork/init.rs @@ -1,9 +1,10 @@ use crate::utils::{ apply_chain_and_block_specific_env_changes, h160_to_b160, h256_to_b256, u256_to_ru256, }; +use alloy_primitives::{Address, U256}; use ethers::{ providers::Middleware, - types::{Address, Block, TxHash, U256}, + types::{Block, TxHash}, }; use eyre::WrapErr; use foundry_common::NON_ARCHIVE_NODE_WARNING; @@ -66,20 +67,21 @@ where // If EIP-3607 is enabled it can cause issues during fuzz/invariant tests if the caller // is a contract. So we disable the check by default. cfg.disable_eip3607 = true; + let mut env = Env { cfg, block: BlockEnv { number: u256_to_ru256(block.number.expect("block number not found").as_u64().into()), - timestamp: block.timestamp.into(), + timestamp: u256_to_ru256(block.timestamp), coinbase: h160_to_b160(block.author.unwrap_or_default()), - difficulty: block.difficulty.into(), + difficulty: u256_to_ru256(block.difficulty), prevrandao: Some(block.mix_hash.map(h256_to_b256).unwrap_or_default()), - basefee: block.base_fee_per_gas.unwrap_or_default().into(), - gas_limit: block.gas_limit.into(), + basefee: u256_to_ru256(block.base_fee_per_gas.unwrap_or_default()), + gas_limit: u256_to_ru256(block.gas_limit), }, tx: TxEnv { - caller: h160_to_b160(origin), - gas_price: gas_price.map(U256::from).unwrap_or(fork_gas_price).into(), + caller: origin, + gas_price: gas_price.map(U256::from).unwrap_or(u256_to_ru256(fork_gas_price)), chain_id: Some(override_chain_id.unwrap_or(rpc_chain_id.as_u64())), gas_limit: block.gas_limit.as_u64(), ..Default::default() diff --git a/crates/evm/src/executor/fork/multi.rs b/crates/evm/src/executor/fork/multi.rs index a3edb576a8608..f2dafbfc333c1 100644 --- a/crates/evm/src/executor/fork/multi.rs +++ b/crates/evm/src/executor/fork/multi.rs @@ -1,4 +1,4 @@ -//! Support for running multiple fork backend +//! Support for running multiple fork backends //! //! The design is similar to the single `SharedBackend`, `BackendHandler` but supports multiple //! concurrently active pairs at once. diff --git a/crates/evm/src/executor/inspector/access_list.rs b/crates/evm/src/executor/inspector/access_list.rs index bd059b2e64d05..108b90ff1f0dd 100644 --- a/crates/evm/src/executor/inspector/access_list.rs +++ b/crates/evm/src/executor/inspector/access_list.rs @@ -1,23 +1,18 @@ -use ethers::{ - abi::{ethereum_types::BigEndianHash, Address}, - types::{ - transaction::eip2930::{AccessList, AccessListItem}, - H256, - }, -}; +use alloy_primitives::{Address, B256}; +use ethers::types::transaction::eip2930::{AccessList, AccessListItem}; use hashbrown::{HashMap, HashSet}; use revm::{ interpreter::{opcode, InstructionResult, Interpreter}, Database, EVMData, Inspector, }; -use crate::utils::{b160_to_h160, ru256_to_u256}; +use crate::utils::{b160_to_h160, b256_to_h256, h160_to_b160, h256_to_b256}; /// An inspector that collects touched accounts and storage slots. #[derive(Default, Debug)] pub struct AccessListTracer { excluded: HashSet
, - access_list: HashMap>, + access_list: HashMap>, } impl AccessListTracer { @@ -32,24 +27,27 @@ impl AccessListTracer { access_list: access_list .0 .iter() - .map(|v| (v.address, v.storage_keys.iter().copied().collect())) + .map(|v| { + ( + h160_to_b160(v.address), + v.storage_keys.iter().copied().map(h256_to_b256).collect(), + ) + }) .collect(), } } - pub fn access_list(&self) -> AccessList { AccessList::from( self.access_list .iter() .map(|(address, slots)| AccessListItem { - address: *address, - storage_keys: slots.iter().copied().collect(), + address: b160_to_h160(*address), + storage_keys: slots.iter().copied().map(b256_to_h256).collect(), }) .collect::>(), ) } } - impl Inspector for AccessListTracer { #[inline] fn step( @@ -61,10 +59,7 @@ impl Inspector for AccessListTracer { opcode::SLOAD | opcode::SSTORE => { if let Ok(slot) = interpreter.stack().peek(0) { let cur_contract = interpreter.contract.address; - self.access_list - .entry(b160_to_h160(cur_contract)) - .or_default() - .insert(H256::from_uint(&ru256_to_u256(slot))); + self.access_list.entry(cur_contract).or_default().insert(slot.into()); } } opcode::EXTCODECOPY | @@ -73,7 +68,7 @@ impl Inspector for AccessListTracer { opcode::BALANCE | opcode::SELFDESTRUCT => { if let Ok(slot) = interpreter.stack().peek(0) { - let addr: Address = H256::from_uint(&ru256_to_u256(slot)).into(); + let addr: Address = Address::from_word(slot.into()); if !self.excluded.contains(&addr) { self.access_list.entry(addr).or_default(); } @@ -81,7 +76,7 @@ impl Inspector for AccessListTracer { } opcode::DELEGATECALL | opcode::CALL | opcode::STATICCALL | opcode::CALLCODE => { if let Ok(slot) = interpreter.stack().peek(1) { - let addr: Address = H256::from_uint(&ru256_to_u256(slot)).into(); + let addr: Address = Address::from_word(slot.into()); if !self.excluded.contains(&addr) { self.access_list.entry(addr).or_default(); } @@ -89,7 +84,6 @@ impl Inspector for AccessListTracer { } _ => (), } - InstructionResult::Continue } } diff --git a/crates/evm/src/executor/inspector/cheatcodes/env.rs b/crates/evm/src/executor/inspector/cheatcodes/env.rs index 70110229ee95f..75463e0f10b1c 100644 --- a/crates/evm/src/executor/inspector/cheatcodes/env.rs +++ b/crates/evm/src/executor/inspector/cheatcodes/env.rs @@ -11,6 +11,7 @@ use crate::{ }, utils::{b160_to_h160, h160_to_b160, ru256_to_u256, u256_to_ru256}, }; +use alloy_primitives::B256; use ethers::{ abi::{self, AbiEncode, RawLog, Token, Tokenizable, Tokenize}, signers::{LocalWallet, Signer}, @@ -18,7 +19,7 @@ use ethers::{ }; use foundry_config::Config; use revm::{ - primitives::{Bytecode, SpecId, B256, KECCAK_EMPTY}, + primitives::{Bytecode, SpecId, KECCAK_EMPTY}, Database, EVMData, }; use std::collections::BTreeMap; @@ -327,7 +328,7 @@ pub fn apply( ) -> Result> { let result = match call { HEVMCalls::Warp(inner) => { - data.env.block.timestamp = inner.0.into(); + data.env.block.timestamp = u256_to_ru256(inner.0); Bytes::new() } HEVMCalls::Difficulty(inner) => { @@ -337,7 +338,7 @@ pub fn apply( use `prevrandao` instead. \ For more information, please see https://eips.ethereum.org/EIPS/eip-4399" ); - data.env.block.difficulty = inner.0.into(); + data.env.block.difficulty = u256_to_ru256(inner.0); Bytes::new() } HEVMCalls::Prevrandao(inner) => { @@ -351,11 +352,11 @@ pub fn apply( Bytes::new() } HEVMCalls::Roll(inner) => { - data.env.block.number = inner.0.into(); + data.env.block.number = u256_to_ru256(inner.0); Bytes::new() } HEVMCalls::Fee(inner) => { - data.env.block.basefee = inner.0.into(); + data.env.block.basefee = u256_to_ru256(inner.0); Bytes::new() } HEVMCalls::Coinbase(inner) => { @@ -395,8 +396,10 @@ pub fn apply( trace!(address=?inner.0, code=?hex::encode(&code), "etch cheatcode"); // TODO: Does this increase gas usage? data.journaled_state.load_account(h160_to_b160(inner.0), data.db)?; - data.journaled_state - .set_code(h160_to_b160(inner.0), Bytecode::new_raw(code.0).to_checked()); + data.journaled_state.set_code( + h160_to_b160(inner.0), + Bytecode::new_raw(alloy_primitives::Bytes(code.0)).to_checked(), + ); Bytes::new() } HEVMCalls::Deal(inner) => { @@ -407,12 +410,12 @@ pub fn apply( // record the deal let record = DealRecord { address: who, - old_balance: account.info.balance.into(), + old_balance: ru256_to_u256(account.info.balance), new_balance: value, }; state.eth_deals.push(record); - account.info.balance = value.into(); + account.info.balance = u256_to_ru256(value); })?; Bytes::new() } @@ -551,7 +554,7 @@ pub fn apply( Bytes::new() } HEVMCalls::TxGasPrice(inner) => { - data.env.tx.gas_price = inner.0.into(); + data.env.tx.gas_price = u256_to_ru256(inner.0); Bytes::new() } HEVMCalls::Broadcast0(_) => { diff --git a/crates/evm/src/executor/inspector/cheatcodes/expect.rs b/crates/evm/src/executor/inspector/cheatcodes/expect.rs index 0f15381144bd6..0feb4f8a88323 100644 --- a/crates/evm/src/executor/inspector/cheatcodes/expect.rs +++ b/crates/evm/src/executor/inspector/cheatcodes/expect.rs @@ -497,7 +497,9 @@ pub fn apply( .as_ref() .map_or(true, Bytecode::is_empty); if empty_bytecode { - let code = Bytecode::new_raw(bytes::Bytes::from_static(&[0u8])).to_checked(); + let code = + Bytecode::new_raw(alloy_primitives::Bytes(bytes::Bytes::from_static(&[0u8]))) + .to_checked(); data.journaled_state.set_code(h160_to_b160(inner.0), code); } state.mocked_calls.entry(inner.0).or_default().insert( diff --git a/crates/evm/src/executor/inspector/cheatcodes/fork.rs b/crates/evm/src/executor/inspector/cheatcodes/fork.rs index 234daeb053322..766457c988c43 100644 --- a/crates/evm/src/executor/inspector/cheatcodes/fork.rs +++ b/crates/evm/src/executor/inspector/cheatcodes/fork.rs @@ -4,13 +4,13 @@ use crate::{ executor::{ backend::DatabaseExt, fork::CreateFork, inspector::cheatcodes::ext::value_to_token, }, - utils::{b160_to_h160, RuntimeOrHandle}, + utils::{h160_to_b160, ru256_to_u256, u256_to_ru256, RuntimeOrHandle}, }; +use alloy_primitives::{B256, U256}; use ethers::{ abi::{self, AbiEncode, Token, Tokenizable, Tokenize}, - prelude::U256, providers::Middleware, - types::{Bytes, Filter, H256}, + types::{Bytes, Filter, U256 as eU256}, }; use foundry_abi::hevm::{EthGetLogsCall, RpcCall}; use foundry_common::ProviderBuilder; @@ -43,43 +43,49 @@ pub fn apply( HEVMCalls::CreateSelectFork2(fork) => { create_select_fork_at_transaction(state, data, fork.0.clone(), fork.1.into()) } - HEVMCalls::SelectFork(fork_id) => select_fork(state, data, fork_id.0), + HEVMCalls::SelectFork(fork_id) => select_fork(state, data, u256_to_ru256(fork_id.0)), HEVMCalls::MakePersistent0(acc) => { - data.db.add_persistent_account(acc.0); + data.db.add_persistent_account(h160_to_b160(acc.0)); Ok(Bytes::new()) } HEVMCalls::MakePersistent1(acc) => { - data.db.extend_persistent_accounts(acc.0.clone()); + data.db.extend_persistent_accounts( + (acc.0.clone().into_iter().map(h160_to_b160)).collect::>(), + ); Ok(Bytes::new()) } HEVMCalls::MakePersistent2(acc) => { - data.db.add_persistent_account(acc.0); - data.db.add_persistent_account(acc.1); + data.db.add_persistent_account(h160_to_b160(acc.0)); + data.db.add_persistent_account(h160_to_b160(acc.1)); Ok(Bytes::new()) } HEVMCalls::MakePersistent3(acc) => { - data.db.add_persistent_account(acc.0); - data.db.add_persistent_account(acc.1); - data.db.add_persistent_account(acc.2); + data.db.add_persistent_account(h160_to_b160(acc.0)); + data.db.add_persistent_account(h160_to_b160(acc.1)); + data.db.add_persistent_account(h160_to_b160(acc.2)); Ok(Bytes::new()) } - HEVMCalls::IsPersistent(acc) => Ok(data.db.is_persistent(&acc.0).encode().into()), + HEVMCalls::IsPersistent(acc) => { + Ok(data.db.is_persistent(&h160_to_b160(acc.0)).encode().into()) + } HEVMCalls::RevokePersistent0(acc) => { - data.db.remove_persistent_account(&acc.0); + data.db.remove_persistent_account(&h160_to_b160(acc.0)); Ok(Bytes::new()) } HEVMCalls::RevokePersistent1(acc) => { - data.db.remove_persistent_accounts(acc.0.clone()); + data.db.remove_persistent_accounts( + acc.0.clone().into_iter().map(h160_to_b160).collect::>(), + ); Ok(Bytes::new()) } HEVMCalls::ActiveFork(_) => data .db .active_fork_id() - .map(|id| id.encode().into()) + .map(|id| ru256_to_u256(id).encode().into()) .ok_or_else(|| fmt_err!("No active fork")), HEVMCalls::RollFork0(fork) => data .db - .roll_fork(None, fork.0, data.env, &mut data.journaled_state) + .roll_fork(None, u256_to_ru256(fork.0), data.env, &mut data.journaled_state) .map(empty) .map_err(Into::into), HEVMCalls::RollFork1(fork) => data @@ -89,13 +95,18 @@ pub fn apply( .map_err(Into::into), HEVMCalls::RollFork2(fork) => data .db - .roll_fork(Some(fork.0), fork.1, data.env, &mut data.journaled_state) + .roll_fork( + Some(fork.0).map(u256_to_ru256), + u256_to_ru256(fork.1), + data.env, + &mut data.journaled_state, + ) .map(empty) .map_err(Into::into), HEVMCalls::RollFork3(fork) => data .db .roll_fork_to_transaction( - Some(fork.0), + Some(fork.0).map(u256_to_ru256), fork.1.into(), data.env, &mut data.journaled_state, @@ -128,7 +139,7 @@ pub fn apply( Ok(urls.encode().into()) } HEVMCalls::AllowCheatcodes(addr) => { - data.db.allow_cheatcode_access(addr.0); + data.db.allow_cheatcode_access(h160_to_b160(addr.0)); Ok(Bytes::new()) } HEVMCalls::Transact0(inner) => data @@ -139,7 +150,7 @@ pub fn apply( HEVMCalls::Transact1(inner) => data .db .transact( - Some(inner.0), + Some(u256_to_ru256(inner.0)), inner.1.into(), data.env, &mut data.journaled_state, @@ -187,7 +198,7 @@ fn create_select_fork( let fork = create_fork_request(state, url_or_alias, block, data)?; let id = data.db.create_select_fork(fork, data.env, &mut data.journaled_state)?; - Ok(id.encode().into()) + Ok(ru256_to_u256(id).encode().into()) } /// Creates a new fork @@ -199,14 +210,14 @@ fn create_fork( ) -> Result { let fork = create_fork_request(state, url_or_alias, block, data)?; let id = data.db.create_fork(fork)?; - Ok(id.encode().into()) + Ok(ru256_to_u256(id).encode().into()) } /// Creates and then also selects the new fork at the given transaction fn create_select_fork_at_transaction( state: &mut Cheatcodes, data: &mut EVMData<'_, DB>, url_or_alias: String, - transaction: H256, + transaction: B256, ) -> Result { if state.broadcast.is_some() { return Err(Error::SelectForkDuringBroadcast) @@ -222,7 +233,7 @@ fn create_select_fork_at_transaction( &mut data.journaled_state, transaction, )?; - Ok(id.encode().into()) + Ok(ru256_to_u256(id).encode().into()) } /// Creates a new fork at the given transaction @@ -230,11 +241,11 @@ fn create_fork_at_transaction( state: &Cheatcodes, data: &mut EVMData<'_, DB>, url_or_alias: String, - transaction: H256, + transaction: B256, ) -> Result { let fork = create_fork_request(state, url_or_alias, None, data)?; let id = data.db.create_fork_at_transaction(fork, transaction)?; - Ok(id.encode().into()) + Ok(ru256_to_u256(id).encode().into()) } /// Creates the request object for a new fork request @@ -260,7 +271,9 @@ fn create_fork_request( /// Equivalent to eth_getLogs but on a cheatcode. fn eth_getlogs(data: &EVMData, inner: &EthGetLogsCall) -> Result { let url = data.db.active_fork_url().ok_or(fmt_err!("No active fork url found"))?; - if inner.0 > U256::from(u64::MAX) || inner.1 > U256::from(u64::MAX) { + if u256_to_ru256(inner.0) > U256::from(u64::MAX) || + u256_to_ru256(inner.1) > U256::from(u64::MAX) + { return Err(fmt_err!("Blocks in block range must be less than 2^64 - 1")) } // Cannot possibly have more than 4 topics in the topics array. @@ -269,16 +282,14 @@ fn eth_getlogs(data: &EVMData, inner: &EthGetLogsCall) -> R } let provider = ProviderBuilder::new(url).build()?; - let mut filter = Filter::new() - .address(b160_to_h160(inner.2.into())) - .from_block(inner.0.as_u64()) - .to_block(inner.1.as_u64()); + let mut filter = + Filter::new().address(inner.2).from_block(inner.0.as_u64()).to_block(inner.1.as_u64()); for (i, item) in inner.3.iter().enumerate() { match i { - 0 => filter = filter.topic0(U256::from(item)), - 1 => filter = filter.topic1(U256::from(item)), - 2 => filter = filter.topic2(U256::from(item)), - 3 => filter = filter.topic3(U256::from(item)), + 0 => filter = filter.topic0(eU256::from(item)), + 1 => filter = filter.topic1(eU256::from(item)), + 2 => filter = filter.topic2(eU256::from(item)), + 3 => filter = filter.topic3(eU256::from(item)), _ => return Err(fmt_err!("Topics array should be less than 4 elements")), }; } diff --git a/crates/evm/src/executor/inspector/cheatcodes/mod.rs b/crates/evm/src/executor/inspector/cheatcodes/mod.rs index 0e048399d4201..ba94fbb9704e3 100644 --- a/crates/evm/src/executor/inspector/cheatcodes/mod.rs +++ b/crates/evm/src/executor/inspector/cheatcodes/mod.rs @@ -10,8 +10,9 @@ use crate::{ backend::DatabaseExt, inspector::cheatcodes::env::RecordedLogs, CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, }, - utils::{b160_to_h160, b256_to_h256, h160_to_b160, ru256_to_u256}, + utils::{b160_to_h160, b256_to_h256, h160_to_b160, ru256_to_u256, u256_to_ru256}, }; +use alloy_primitives::{Address as rAddress, B256}; use ethers::{ abi::{AbiDecode, AbiEncode, RawLog}, signers::LocalWallet, @@ -25,7 +26,7 @@ use foundry_utils::error::SolError; use itertools::Itertools; use revm::{ interpreter::{opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}, - primitives::{BlockEnv, TransactTo, B160, B256}, + primitives::{BlockEnv, TransactTo}, EVMData, Inspector, }; use serde_json::Value; @@ -220,7 +221,7 @@ impl Cheatcodes { // ensure the caller is allowed to execute cheatcodes, // but only if the backend is in forking mode - data.db.ensure_cheatcode_access_forking_mode(caller)?; + data.db.ensure_cheatcode_access_forking_mode(h160_to_b160(caller))?; let opt = env::apply(self, data, caller, &decoded) .transpose() @@ -255,9 +256,7 @@ impl Cheatcodes { .unwrap_or_default(); let created_address = get_create_address(inputs, old_nonce); - if data.journaled_state.depth > 1 && - !data.db.has_cheatcode_access(b160_to_h160(inputs.caller)) - { + if data.journaled_state.depth > 1 && !data.db.has_cheatcode_access(inputs.caller) { // we only grant cheat code access for new contracts if the caller also has // cheatcode access and the new contract is created in top most call return @@ -288,7 +287,7 @@ impl Cheatcodes { // which rolls back any transfers. while let Some(record) = self.eth_deals.pop() { if let Some(acc) = data.journaled_state.state.get_mut(&h160_to_b160(record.address)) { - acc.info.balance = record.old_balance.into(); + acc.info.balance = u256_to_ru256(record.old_balance); } } } @@ -307,7 +306,7 @@ impl Inspector for Cheatcodes { data.env.block = block; } if let Some(gas_price) = self.gas_price.take() { - data.env.tx.gas_price = gas_price.into(); + data.env.tx.gas_price = u256_to_ru256(gas_price); } InstructionResult::Continue @@ -386,7 +385,7 @@ impl Inspector for Cheatcodes { .reads .entry(b160_to_h160(interpreter.contract().address)) .or_insert_with(Vec::new) - .push(key.into()); + .push(ru256_to_u256(key)); } opcode::SSTORE => { let key = try_or_continue!(interpreter.stack().peek(0)); @@ -396,12 +395,12 @@ impl Inspector for Cheatcodes { .reads .entry(b160_to_h160(interpreter.contract().address)) .or_insert_with(Vec::new) - .push(key.into()); + .push(ru256_to_u256(key)); storage_accesses .writes .entry(b160_to_h160(interpreter.contract().address)) .or_insert_with(Vec::new) - .push(key.into()); + .push(ru256_to_u256(key)); } _ => (), } @@ -541,9 +540,9 @@ impl Inspector for Cheatcodes { fn log( &mut self, _: &mut EVMData<'_, DB>, - address: &B160, + address: &rAddress, topics: &[B256], - data: &bytes::Bytes, + data: &alloy_primitives::Bytes, ) { if !self.expected_emits.is_empty() { handle_expect_emit( @@ -572,14 +571,16 @@ impl Inspector for Cheatcodes { &mut self, data: &mut EVMData<'_, DB>, call: &mut CallInputs, - ) -> (InstructionResult, Gas, bytes::Bytes) { - if call.contract == h160_to_b160(CHEATCODE_ADDRESS) { + ) -> (InstructionResult, Gas, alloy_primitives::Bytes) { + if call.contract == CHEATCODE_ADDRESS { let gas = Gas::new(call.gas_limit); match self.apply_cheatcode(data, b160_to_h160(call.context.caller), call) { - Ok(retdata) => (InstructionResult::Return, gas, retdata.0), - Err(err) => (InstructionResult::Revert, gas, err.encode_error().0), + Ok(retdata) => (InstructionResult::Return, gas, alloy_primitives::Bytes(retdata.0)), + Err(err) => { + (InstructionResult::Revert, gas, alloy_primitives::Bytes(err.encode_error().0)) + } } - } else if call.contract != h160_to_b160(HARDHAT_CONSOLE_ADDRESS) { + } else if call.contract != HARDHAT_CONSOLE_ADDRESS { // Handle expected calls // Grab the different calldatas expected. @@ -596,7 +597,7 @@ impl Inspector for Cheatcodes { // The value matches, if provided expected .value - .map_or(true, |value| value == call.transfer.value.into()) && + .map_or(true, |value| value == ru256_to_u256(call.transfer.value)) && // The gas matches, if provided expected.gas.map_or(true, |gas| gas == call.gas_limit) && // The minimum gas matches, if provided @@ -610,24 +611,25 @@ impl Inspector for Cheatcodes { // Handle mocked calls if let Some(mocks) = self.mocked_calls.get(&b160_to_h160(call.contract)) { let ctx = MockCallDataContext { - calldata: call.input.clone().into(), - value: Some(call.transfer.value.into()), + calldata: ethers::types::Bytes::from(call.input.clone().0), + value: Some(call.transfer.value).map(ru256_to_u256), }; if let Some(mock_retdata) = mocks.get(&ctx) { return ( mock_retdata.ret_type, Gas::new(call.gas_limit), - mock_retdata.data.clone().0, + alloy_primitives::Bytes(mock_retdata.data.clone().0), ) } else if let Some((_, mock_retdata)) = mocks.iter().find(|(mock, _)| { mock.calldata.len() <= call.input.len() && *mock.calldata == call.input[..mock.calldata.len()] && - mock.value.map_or(true, |value| value == call.transfer.value.into()) + mock.value + .map_or(true, |value| value == ru256_to_u256(call.transfer.value)) }) { return ( mock_retdata.ret_type, Gas::new(call.gas_limit), - mock_retdata.data.0.clone(), + alloy_primitives::Bytes(mock_retdata.data.0.clone()), ) } } @@ -688,7 +690,7 @@ impl Inspector for Cheatcodes { return ( InstructionResult::Revert, Gas::new(call.gas_limit), - err.encode_string().0, + alloy_primitives::Bytes(err.encode_string().0), ) } @@ -705,8 +707,8 @@ impl Inspector for Cheatcodes { transaction: TypedTransaction::Legacy(TransactionRequest { from: Some(broadcast.new_origin), to: Some(NameOrAddress::Address(b160_to_h160(call.contract))), - value: Some(call.transfer.value.into()), - data: Some(call.input.clone().into()), + value: Some(call.transfer.value).map(ru256_to_u256), + data: Some(call.input.clone().0).map(ethers::types::Bytes), nonce: Some(account.info.nonce.into()), gas: if is_fixed_gas_limit { Some(call.gas_limit.into()) @@ -732,9 +734,9 @@ impl Inspector for Cheatcodes { } } - (InstructionResult::Continue, Gas::new(call.gas_limit), bytes::Bytes::new()) + (InstructionResult::Continue, Gas::new(call.gas_limit), alloy_primitives::Bytes::new()) } else { - (InstructionResult::Continue, Gas::new(call.gas_limit), bytes::Bytes::new()) + (InstructionResult::Continue, Gas::new(call.gas_limit), alloy_primitives::Bytes::new()) } } @@ -744,11 +746,9 @@ impl Inspector for Cheatcodes { call: &CallInputs, remaining_gas: Gas, status: InstructionResult, - retdata: bytes::Bytes, - ) -> (InstructionResult, Gas, bytes::Bytes) { - if call.contract == h160_to_b160(CHEATCODE_ADDRESS) || - call.contract == h160_to_b160(HARDHAT_CONSOLE_ADDRESS) - { + retdata: alloy_primitives::Bytes, + ) -> (InstructionResult, Gas, alloy_primitives::Bytes) { + if call.contract == CHEATCODE_ADDRESS || call.contract == HARDHAT_CONSOLE_ADDRESS { return (status, remaining_gas, retdata) } @@ -756,7 +756,7 @@ impl Inspector for Cheatcodes { return ( InstructionResult::Revert, remaining_gas, - Error::custom_bytes(MAGIC_SKIP_BYTES).encode_error().0, + alloy_primitives::Bytes(Error::custom_bytes(MAGIC_SKIP_BYTES).encode_error().0), ) } @@ -792,13 +792,21 @@ impl Inspector for Cheatcodes { false, expected_revert.reason.as_ref(), status, - retdata.into(), + ethers::types::Bytes(retdata.0), ) { Err(error) => { trace!(expected=?expected_revert, ?error, ?status, "Expected revert mismatch"); - (InstructionResult::Revert, remaining_gas, error.encode_error().0) + ( + InstructionResult::Revert, + remaining_gas, + alloy_primitives::Bytes(error.encode_error().0), + ) } - Ok((_, retdata)) => (InstructionResult::Return, remaining_gas, retdata.0), + Ok((_, retdata)) => ( + InstructionResult::Return, + remaining_gas, + alloy_primitives::Bytes(retdata.0), + ), } } } @@ -946,7 +954,7 @@ impl Inspector for Cheatcodes { call.contract != test_contract { self.fork_revert_diagnostic = - data.db.diagnose_revert(b160_to_h160(call.contract), &data.journaled_state); + data.db.diagnose_revert(call.contract, &data.journaled_state); } } @@ -957,7 +965,7 @@ impl Inspector for Cheatcodes { &mut self, data: &mut EVMData<'_, DB>, call: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, bytes::Bytes) { + ) -> (InstructionResult, Option, Gas, alloy_primitives::Bytes) { // allow cheatcodes from the address of the new contract self.allow_cheatcodes_on_create(data, call); @@ -990,7 +998,7 @@ impl Inspector for Cheatcodes { InstructionResult::Revert, None, Gas::new(call.gas_limit), - err.encode_string().0, + alloy_primitives::Bytes(err.encode_string().0), ) } @@ -999,7 +1007,7 @@ impl Inspector for Cheatcodes { if data.journaled_state.depth() == broadcast.depth { let (bytecode, to, nonce) = match process_create( broadcast.new_origin, - call.init_code.clone(), + call.init_code.clone().0, data, call, ) { @@ -1009,7 +1017,7 @@ impl Inspector for Cheatcodes { InstructionResult::Revert, None, Gas::new(call.gas_limit), - err.encode_string().0, + alloy_primitives::Bytes(err.encode_string().0), ) } }; @@ -1021,7 +1029,7 @@ impl Inspector for Cheatcodes { transaction: TypedTransaction::Legacy(TransactionRequest { from: Some(broadcast.new_origin), to, - value: Some(call.value.into()), + value: Some(call.value).map(ru256_to_u256), data: Some(bytecode.into()), nonce: Some(nonce.into()), gas: if is_fixed_gas_limit { @@ -1036,7 +1044,12 @@ impl Inspector for Cheatcodes { } } - (InstructionResult::Continue, None, Gas::new(call.gas_limit), bytes::Bytes::new()) + ( + InstructionResult::Continue, + None, + Gas::new(call.gas_limit), + alloy_primitives::Bytes::new(), + ) } fn create_end( @@ -1044,10 +1057,10 @@ impl Inspector for Cheatcodes { data: &mut EVMData<'_, DB>, _: &CreateInputs, status: InstructionResult, - address: Option, + address: Option, remaining_gas: Gas, - retdata: bytes::Bytes, - ) -> (InstructionResult, Option, Gas, bytes::Bytes) { + retdata: alloy_primitives::Bytes, + ) -> (InstructionResult, Option, Gas, alloy_primitives::Bytes) { // Clean up pranks if let Some(prank) = &self.prank { if data.journaled_state.depth() == prank.depth { @@ -1080,17 +1093,20 @@ impl Inspector for Cheatcodes { true, expected_revert.reason.as_ref(), status, - retdata.into(), + ethers::types::Bytes(retdata.0), ) { Ok((address, retdata)) => ( InstructionResult::Return, address.map(h160_to_b160), remaining_gas, - retdata.0, + alloy_primitives::Bytes(retdata.0), + ), + Err(err) => ( + InstructionResult::Revert, + None, + remaining_gas, + alloy_primitives::Bytes(err.encode_error().0), ), - Err(err) => { - (InstructionResult::Revert, None, remaining_gas, err.encode_error().0) - } } } } diff --git a/crates/evm/src/executor/inspector/cheatcodes/snapshot.rs b/crates/evm/src/executor/inspector/cheatcodes/snapshot.rs index f34d61e54038e..1449155ad5afa 100644 --- a/crates/evm/src/executor/inspector/cheatcodes/snapshot.rs +++ b/crates/evm/src/executor/inspector/cheatcodes/snapshot.rs @@ -1,5 +1,9 @@ use super::Result; -use crate::{abi::HEVMCalls, executor::backend::DatabaseExt}; +use crate::{ + abi::HEVMCalls, + executor::backend::DatabaseExt, + utils::{ru256_to_u256, u256_to_ru256}, +}; use ethers::abi::AbiEncode; use revm::EVMData; @@ -8,11 +12,11 @@ use revm::EVMData; pub fn apply(data: &mut EVMData<'_, DB>, call: &HEVMCalls) -> Option { Some(match call { HEVMCalls::Snapshot(_) => { - Ok(data.db.snapshot(&data.journaled_state, data.env).encode().into()) + Ok(ru256_to_u256(data.db.snapshot(&data.journaled_state, data.env)).encode().into()) } HEVMCalls::RevertTo(snapshot) => { let res = if let Some(journaled_state) = - data.db.revert(snapshot.0, &data.journaled_state, data.env) + data.db.revert(u256_to_ru256(snapshot.0), &data.journaled_state, data.env) { // we reset the evm's journaled_state to the state of the snapshot previous state data.journaled_state = journaled_state; diff --git a/crates/evm/src/executor/inspector/cheatcodes/util.rs b/crates/evm/src/executor/inspector/cheatcodes/util.rs index 886948e7e7890..c59937a3a7c10 100644 --- a/crates/evm/src/executor/inspector/cheatcodes/util.rs +++ b/crates/evm/src/executor/inspector/cheatcodes/util.rs @@ -4,8 +4,9 @@ use crate::{ error::{DatabaseError, DatabaseResult}, DatabaseExt, }, - utils::{h160_to_b160, h256_to_u256_be, ru256_to_u256, u256_to_ru256}, + utils::{b160_to_h160, h160_to_b160, h256_to_u256_be, ru256_to_u256, u256_to_ru256}, }; +use alloy_primitives::Address as rAddress; use bytes::{BufMut, Bytes, BytesMut}; use ethers::{ abi::Address, @@ -27,7 +28,7 @@ use std::collections::VecDeque; pub const MAGIC_SKIP_BYTES: &[u8] = b"FOUNDRY::SKIP"; /// Address of the default CREATE2 deployer 0x4e59b44847b379578588920ca78fbf26c0b4956c -pub const DEFAULT_CREATE2_DEPLOYER: H160 = H160([ +pub const DEFAULT_CREATE2_DEPLOYER: rAddress = rAddress::new([ 78, 89, 180, 72, 71, 179, 121, 87, 133, 136, 146, 12, 167, 143, 191, 38, 192, 180, 149, 108, ]); @@ -44,8 +45,8 @@ pub type BroadcastableTransactions = VecDeque; pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction) { env.tx.caller = h160_to_b160(tx.from); env.tx.gas_limit = tx.gas.as_u64(); - env.tx.gas_price = tx.gas_price.unwrap_or_default().into(); - env.tx.gas_priority_fee = tx.max_priority_fee_per_gas.map(Into::into); + env.tx.gas_price = u256_to_ru256(tx.gas_price.unwrap_or_default()); + env.tx.gas_priority_fee = tx.max_priority_fee_per_gas.map(u256_to_ru256); env.tx.nonce = Some(tx.nonce.as_u64()); env.tx.access_list = tx .access_list @@ -60,8 +61,8 @@ pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction) { ) }) .collect(); - env.tx.value = tx.value.into(); - env.tx.data = tx.input.0.clone(); + env.tx.value = u256_to_ru256(tx.value); + env.tx.data = alloy_primitives::Bytes(tx.input.0.clone()); env.tx.transact_to = tx.to.map(h160_to_b160).map(TransactTo::Call).unwrap_or_else(TransactTo::create) } @@ -103,9 +104,9 @@ where } revm::primitives::CreateScheme::Create2 { salt } => { // Sanity checks for our CREATE2 deployer - data.journaled_state.load_account(h160_to_b160(DEFAULT_CREATE2_DEPLOYER), data.db)?; + data.journaled_state.load_account(DEFAULT_CREATE2_DEPLOYER, data.db)?; - let info = &data.journaled_state.account(h160_to_b160(DEFAULT_CREATE2_DEPLOYER)).info; + let info = &data.journaled_state.account(DEFAULT_CREATE2_DEPLOYER).info; match &info.code { Some(code) => { if code.is_empty() { @@ -122,7 +123,7 @@ where } } - call.caller = h160_to_b160(DEFAULT_CREATE2_DEPLOYER); + call.caller = DEFAULT_CREATE2_DEPLOYER; // We have to increment the nonce of the user address, since this create2 will be done // by the create2_deployer @@ -138,7 +139,11 @@ where calldata.put_slice(&salt_bytes); calldata.put(bytecode); - Ok((calldata.freeze(), Some(NameOrAddress::Address(DEFAULT_CREATE2_DEPLOYER)), nonce)) + Ok(( + calldata.freeze(), + Some(NameOrAddress::Address(b160_to_h160(DEFAULT_CREATE2_DEPLOYER))), + nonce, + )) } } } @@ -165,8 +170,8 @@ pub fn check_if_fixed_gas_limit( // time of the call, which should be rather close to configured gas limit. // TODO: Find a way to reliably make this determination. (for example by // generating it in the compilation or evm simulation process) - U256::from(data.env.tx.gas_limit) > data.env.block.gas_limit.into() && - U256::from(call_gas_limit) <= data.env.block.gas_limit.into() + U256::from(data.env.tx.gas_limit) > ru256_to_u256(data.env.block.gas_limit) && + U256::from(call_gas_limit) <= ru256_to_u256(data.env.block.gas_limit) // Transfers in forge scripts seem to be estimated at 2300 by revm leading to "Intrinsic // gas too low" failure when simulated on chain && call_gas_limit > 2300 diff --git a/crates/evm/src/executor/inspector/debugger.rs b/crates/evm/src/executor/inspector/debugger.rs index 9c49326056dc6..2e59b1f700298 100644 --- a/crates/evm/src/executor/inspector/debugger.rs +++ b/crates/evm/src/executor/inspector/debugger.rs @@ -5,18 +5,15 @@ use crate::{ inspector::utils::{gas_used, get_create_address}, CHEATCODE_ADDRESS, }, - utils::b160_to_h160, CallKind, }; -use bytes::Bytes; -use ethers::types::Address; +use alloy_primitives::{Address, Bytes}; use foundry_utils::error::SolError; use revm::{ interpreter::{ opcode::{self, spec_opcode_gas}, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, Memory, }, - primitives::B160, EVMData, Inspector, }; @@ -82,7 +79,7 @@ impl Inspector for Debugger { self.arena.arena[self.head].steps.push(DebugStep { pc, - stack: interpreter.stack().data().iter().copied().map(|d| d.into()).collect(), + stack: interpreter.stack().data().clone(), memory: interpreter.memory.clone(), instruction: Instruction::OpCode(op), push_bytes, @@ -100,10 +97,10 @@ impl Inspector for Debugger { ) -> (InstructionResult, Gas, Bytes) { self.enter( data.journaled_state.depth() as usize, - b160_to_h160(call.context.code_address), + call.context.code_address, call.context.scheme.into(), ); - if CHEATCODE_ADDRESS == b160_to_h160(call.contract) { + if CHEATCODE_ADDRESS == call.contract { self.arena.arena[self.head].steps.push(DebugStep { memory: Memory::new(), instruction: Instruction::Cheatcode( @@ -135,11 +132,16 @@ impl Inspector for Debugger { &mut self, data: &mut EVMData<'_, DB>, call: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { // TODO: Does this increase gas cost? if let Err(err) = data.journaled_state.load_account(call.caller, data.db) { let gas = Gas::new(call.gas_limit); - return (InstructionResult::Revert, None, gas, err.encode_string().0) + return ( + InstructionResult::Revert, + None, + gas, + alloy_primitives::Bytes(err.encode_string().0), + ) } let nonce = data.journaled_state.account(call.caller).info.nonce; @@ -158,10 +160,10 @@ impl Inspector for Debugger { _: &mut EVMData<'_, DB>, _: &CreateInputs, status: InstructionResult, - address: Option, + address: Option
, gas: Gas, retdata: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { self.exit(); (status, address, gas, retdata) diff --git a/crates/evm/src/executor/inspector/fuzzer.rs b/crates/evm/src/executor/inspector/fuzzer.rs index a7363614a01a2..be46192c92974 100644 --- a/crates/evm/src/executor/inspector/fuzzer.rs +++ b/crates/evm/src/executor/inspector/fuzzer.rs @@ -2,7 +2,7 @@ use crate::{ fuzz::{invariant::RandomCallGenerator, strategies::EvmFuzzState}, utils::{self, b160_to_h160, h160_to_b160}, }; -use bytes::Bytes; +use alloy_primitives::Bytes; use revm::{ interpreter::{CallInputs, CallScheme, Gas, InstructionResult, Interpreter}, Database, EVMData, Inspector, @@ -103,7 +103,7 @@ impl Fuzzer { if let Some((sender, (contract, input))) = call_generator .next(b160_to_h160(call.context.caller), b160_to_h160(call.contract)) { - call.input = input.0; + *call.input = input.0; call.context.caller = h160_to_b160(sender); call.contract = h160_to_b160(contract); diff --git a/crates/evm/src/executor/inspector/logs.rs b/crates/evm/src/executor/inspector/logs.rs index a4124d4695a62..56b9897a7aaa8 100644 --- a/crates/evm/src/executor/inspector/logs.rs +++ b/crates/evm/src/executor/inspector/logs.rs @@ -1,16 +1,15 @@ use crate::{ executor::{patch_hardhat_console_selector, HardhatConsoleCalls, HARDHAT_CONSOLE_ADDRESS}, - utils::{b160_to_h160, b256_to_h256, h160_to_b160}, + utils::{b160_to_h160, b256_to_h256}, }; -use bytes::Bytes; +use alloy_primitives::{Address, Bytes, B256}; use ethers::{ abi::{AbiDecode, Token}, - types::{Log, H256}, + types::{Bytes as ethersBytes, Log, H256}, }; use foundry_macros::ConsoleFmt; use revm::{ interpreter::{CallInputs, Gas, InstructionResult}, - primitives::{B160, B256}, Database, EVMData, Inspector, }; @@ -44,11 +43,11 @@ impl LogCollector { } impl Inspector for LogCollector { - fn log(&mut self, _: &mut EVMData<'_, DB>, address: &B160, topics: &[B256], data: &Bytes) { + fn log(&mut self, _: &mut EVMData<'_, DB>, address: &Address, topics: &[B256], data: &Bytes) { self.logs.push(Log { address: b160_to_h160(*address), topics: topics.iter().copied().map(b256_to_h256).collect(), - data: data.clone().into(), + data: ethersBytes::from(data.clone().0), ..Default::default() }); } @@ -58,7 +57,7 @@ impl Inspector for LogCollector { _: &mut EVMData<'_, DB>, call: &mut CallInputs, ) -> (InstructionResult, Gas, Bytes) { - if call.contract == h160_to_b160(HARDHAT_CONSOLE_ADDRESS) { + if call.contract == HARDHAT_CONSOLE_ADDRESS { let (status, reason) = self.hardhat_log(call.input.to_vec()); (status, Gas::new(call.gas_limit), reason) } else { diff --git a/crates/evm/src/executor/inspector/printer.rs b/crates/evm/src/executor/inspector/printer.rs index 0f8d9127bf87b..a4afb10373c35 100644 --- a/crates/evm/src/executor/inspector/printer.rs +++ b/crates/evm/src/executor/inspector/printer.rs @@ -1,7 +1,6 @@ -use bytes::Bytes; +use alloy_primitives::{Address, Bytes}; use revm::{ interpreter::{opcode, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}, - primitives::B160, Database, EVMData, Inspector, }; @@ -54,7 +53,7 @@ impl Inspector for TracePrinter { &mut self, _data: &mut EVMData<'_, DB>, inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { println!( "CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}", inputs.caller, diff --git a/crates/evm/src/executor/inspector/stack.rs b/crates/evm/src/executor/inspector/stack.rs index 759131d3088e2..5c97b6ca8e4f7 100644 --- a/crates/evm/src/executor/inspector/stack.rs +++ b/crates/evm/src/executor/inspector/stack.rs @@ -6,17 +6,15 @@ use crate::{ debug::DebugArena, executor::{backend::DatabaseExt, inspector::CoverageCollector}, trace::CallTraceArena, + utils::{h160_to_b160, ru256_to_u256}, }; -use bytes::Bytes; -use ethers::{ - signers::LocalWallet, - types::{Address, Log, U256}, -}; +use alloy_primitives::{Address, Bytes, B256, U256}; +use ethers::{signers::LocalWallet, types::Log}; use revm::{ interpreter::{ return_revert, CallInputs, CreateInputs, Gas, InstructionResult, Interpreter, Memory, Stack, }, - primitives::{BlockEnv, Env, B160, B256, U256 as rU256}, + primitives::{BlockEnv, Env}, EVMData, Inspector, }; use std::{collections::BTreeMap, sync::Arc}; @@ -229,7 +227,7 @@ impl InspectorStack { #[inline] pub fn set_env(&mut self, env: &Env) { self.set_block(&env.block); - self.set_gas_price(env.tx.gas_price.into()); + self.set_gas_price(env.tx.gas_price); } /// Sets the block for the relevant inspectors. @@ -244,7 +242,7 @@ impl InspectorStack { #[inline] pub fn set_gas_price(&mut self, gas_price: U256) { if let Some(cheatcodes) = &mut self.cheatcodes { - cheatcodes.gas_price = Some(gas_price); + cheatcodes.gas_price = Some(gas_price).map(ru256_to_u256); } } @@ -304,7 +302,14 @@ impl InspectorStack { labels: self .cheatcodes .as_ref() - .map(|cheatcodes| cheatcodes.labels.clone()) + .map(|cheatcodes| { + cheatcodes + .labels + .clone() + .into_iter() + .map(|l| (h160_to_b160(l.0), l.1)) + .collect() + }) .unwrap_or_default(), traces: self.tracer.map(|tracer| tracer.traces), debug: self.debugger.map(|debugger| debugger.arena), @@ -414,7 +419,7 @@ impl Inspector for InspectorStack { fn log( &mut self, evm_data: &mut EVMData<'_, DB>, - address: &B160, + address: &Address, topics: &[B256], data: &Bytes, ) { @@ -508,7 +513,7 @@ impl Inspector for InspectorStack { &mut self, data: &mut EVMData<'_, DB>, call: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { call_inspectors!( [ &mut self.debugger, @@ -536,10 +541,10 @@ impl Inspector for InspectorStack { data: &mut EVMData<'_, DB>, call: &CreateInputs, status: InstructionResult, - address: Option, + address: Option
, remaining_gas: Gas, retdata: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { call_inspectors!( [ &mut self.debugger, @@ -568,7 +573,7 @@ impl Inspector for InspectorStack { (status, address, remaining_gas, retdata) } - fn selfdestruct(&mut self, contract: B160, target: B160, value: rU256) { + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { call_inspectors!( [ &mut self.debugger, diff --git a/crates/evm/src/executor/inspector/tracer.rs b/crates/evm/src/executor/inspector/tracer.rs index 77609946c6e8a..392ae6c1a6196 100644 --- a/crates/evm/src/executor/inspector/tracer.rs +++ b/crates/evm/src/executor/inspector/tracer.rs @@ -8,17 +8,13 @@ use crate::{ utils::{b160_to_h160, b256_to_h256, ru256_to_u256}, CallKind, }; -use bytes::Bytes; -use ethers::{ - abi::RawLog, - types::{Address, U256}, -}; +use alloy_primitives::{Address, Bytes, B256, U256}; +use ethers::abi::RawLog; use revm::{ interpreter::{ opcode, return_ok, CallInputs, CallScheme, CreateInputs, Gas, InstructionResult, Interpreter, }, - primitives::{B160, B256}, Database, EVMData, Inspector, JournalEntry, }; @@ -50,12 +46,12 @@ impl Tracer { 0, CallTrace { depth, - address, + address: b160_to_h160(address), kind, data: RawOrDecodedCall::Raw(data.into()), - value, + value: ru256_to_u256(value), status: InstructionResult::Continue, - caller, + caller: b160_to_h160(caller), ..Default::default() }, )); @@ -78,7 +74,7 @@ impl Tracer { trace.output = RawOrDecodedReturnData::Raw(output.into()); if let Some(address) = address { - trace.address = address; + trace.address = b160_to_h160(address); } } @@ -128,7 +124,7 @@ impl Tracer { Some(JournalEntry::StorageChange { address, key, .. }), ) => { let value = data.journaled_state.state[address].storage[key].present_value(); - Some((ru256_to_u256(*key), value.into())) + Some((ru256_to_u256(*key), ru256_to_u256(value))) } _ => None, }; @@ -165,7 +161,7 @@ impl Inspector for Tracer { } #[inline] - fn log(&mut self, _: &mut EVMData<'_, DB>, _: &B160, topics: &[B256], data: &Bytes) { + fn log(&mut self, _: &mut EVMData<'_, DB>, _: &Address, topics: &[B256], data: &Bytes) { let node = &mut self.traces.arena[*self.trace_stack.last().expect("no ongoing trace")]; let topics: Vec<_> = topics.iter().copied().map(b256_to_h256).collect(); node.ordering.push(LogCallOrder::Log(node.logs.len())); @@ -187,11 +183,11 @@ impl Inspector for Tracer { self.start_trace( data.journaled_state.depth() as usize, - b160_to_h160(to), + to, inputs.input.to_vec(), - inputs.transfer.value.into(), + inputs.transfer.value, inputs.context.scheme.into(), - b160_to_h160(from), + from, ); (InstructionResult::Continue, Gas::new(inputs.gas_limit), Bytes::new()) @@ -221,7 +217,7 @@ impl Inspector for Tracer { &mut self, data: &mut EVMData<'_, DB>, inputs: &mut CreateInputs, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { // TODO: Does this increase gas cost? let _ = data.journaled_state.load_account(inputs.caller, data.db); let nonce = data.journaled_state.account(inputs.caller).info.nonce; @@ -229,9 +225,9 @@ impl Inspector for Tracer { data.journaled_state.depth() as usize, get_create_address(inputs, nonce), inputs.init_code.to_vec(), - inputs.value.into(), + inputs.value, inputs.scheme.into(), - b160_to_h160(inputs.caller), + inputs.caller, ); (InstructionResult::Continue, None, Gas::new(inputs.gas_limit), Bytes::new()) @@ -243,10 +239,10 @@ impl Inspector for Tracer { data: &mut EVMData<'_, DB>, _inputs: &CreateInputs, status: InstructionResult, - address: Option, + address: Option
, gas: Gas, retdata: Bytes, - ) -> (InstructionResult, Option, Gas, Bytes) { + ) -> (InstructionResult, Option
, Gas, Bytes) { let code = match address { Some(address) => data .journaled_state @@ -261,7 +257,7 @@ impl Inspector for Tracer { status, gas_used(data.env.cfg.spec_id, gas.spend(), gas.refunded() as u64), code, - address.map(b160_to_h160), + address, ); (status, address, gas, retdata) diff --git a/crates/evm/src/executor/inspector/utils.rs b/crates/evm/src/executor/inspector/utils.rs index 22fecc6b7b05d..5c828e8ac9bd0 100644 --- a/crates/evm/src/executor/inspector/utils.rs +++ b/crates/evm/src/executor/inspector/utils.rs @@ -1,14 +1,10 @@ -use ethers::{ - types::Address, - utils::{get_contract_address, get_create2_address}, -}; +use alloy_primitives::{Address, B256}; + use revm::{ interpreter::CreateInputs, primitives::{CreateScheme, SpecId}, }; -use crate::utils::{b160_to_h160, ru256_to_u256}; - /// Returns [InstructionResult::Continue] on an error, discarding the error. /// /// Useful for inspectors that read state that might be invalid, but do not want to emit @@ -25,12 +21,9 @@ macro_rules! try_or_continue { /// Get the address of a contract creation pub fn get_create_address(call: &CreateInputs, nonce: u64) -> Address { match call.scheme { - CreateScheme::Create => get_contract_address(b160_to_h160(call.caller), nonce), + CreateScheme::Create => call.caller.create(nonce), CreateScheme::Create2 { salt } => { - let salt = ru256_to_u256(salt); - let mut salt_bytes = [0u8; 32]; - salt.to_big_endian(&mut salt_bytes); - get_create2_address(b160_to_h160(call.caller), salt_bytes, call.init_code.clone()) + call.caller.create2_from_code(B256::from(salt), &call.init_code) } } } diff --git a/crates/evm/src/executor/mod.rs b/crates/evm/src/executor/mod.rs index d07d1bd112c79..cc7f03c0d7d39 100644 --- a/crates/evm/src/executor/mod.rs +++ b/crates/evm/src/executor/mod.rs @@ -1,33 +1,35 @@ +//! Main Foundry executor abstractions, which can execute calls. +//! Used for running tests, scripts, and interacting with the inner backend which holds the state. + use self::inspector::{cheatcodes::util::BroadcastableTransactions, Cheatcodes, InspectorData}; use crate::{ debug::DebugArena, decode, trace::CallTraceArena, - utils::{b160_to_h160, eval_to_instruction_result, h160_to_b160, halt_to_instruction_result}, + utils::{eval_to_instruction_result, halt_to_instruction_result}, CALLER, }; pub use abi::{ patch_hardhat_console_selector, HardhatConsoleCalls, CHEATCODE_ADDRESS, CONSOLE_ABI, HARDHAT_CONSOLE_ABI, HARDHAT_CONSOLE_ADDRESS, }; +/// Reexport commonly used revm types +pub use alloy_primitives::{Address, Bytes, U256}; use backend::FuzzBackendWrapper; -use bytes::Bytes; use ethers::{ abi::{Abi, Contract, Detokenize, Function, Tokenize}, - prelude::{decode_function_data, encode_function_data, Address, U256}, + prelude::{decode_function_data, encode_function_data}, signers::LocalWallet, types::Log, }; use foundry_common::{abi::IntoFunction, evm::Breakpoints}; use revm::primitives::hex_literal::hex; -/// Reexport commonly used revm types -pub use revm::primitives::{Env, SpecId}; pub use revm::{ db::{DatabaseCommit, DatabaseRef}, interpreter::{return_ok, CreateScheme, InstructionResult, Memory, Stack}, primitives::{ - Account, BlockEnv, Bytecode, ExecutionResult, HashMap, Output, ResultAndState, TransactTo, - TxEnv, B160, U256 as rU256, + Account, BlockEnv, Bytecode, Env, ExecutionResult, HashMap, Output, ResultAndState, SpecId, + TransactTo, TxEnv, }, }; use std::collections::BTreeMap; @@ -60,7 +62,7 @@ use crate::{ pub use builder::ExecutorBuilder; /// A mapping of addresses to their changed state. -pub type StateChangeset = HashMap; +pub type StateChangeset = HashMap; /// The initcode of the default create2 deployer. pub const DEFAULT_CREATE2_DEPLOYER_CODE: &[u8] = &hex!("604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"); @@ -116,7 +118,7 @@ impl Executor { trace!("deploying local create2 deployer"); let create2_deployer_account = self .backend - .basic(h160_to_b160(DEFAULT_CREATE2_DEPLOYER))? + .basic(DEFAULT_CREATE2_DEPLOYER)? .ok_or(DatabaseError::MissingAccount(DEFAULT_CREATE2_DEPLOYER))?; // if the deployer is not currently deployed, deploy the default one @@ -128,7 +130,7 @@ impl Executor { self.set_balance(creator, U256::MAX)?; let res = - self.deploy(creator, DEFAULT_CREATE2_DEPLOYER_CODE.into(), U256::zero(), None)?; + self.deploy(creator, DEFAULT_CREATE2_DEPLOYER_CODE.into(), U256::ZERO, None)?; trace!(create2=?res.address, "deployed local create2 deployer"); self.set_balance(creator, initial_balance)?; @@ -139,8 +141,8 @@ impl Executor { /// Set the balance of an account. pub fn set_balance(&mut self, address: Address, amount: U256) -> DatabaseResult<&mut Self> { trace!(?address, ?amount, "setting account balance"); - let mut account = self.backend.basic(h160_to_b160(address))?.unwrap_or_default(); - account.balance = amount.into(); + let mut account = self.backend.basic(address)?.unwrap_or_default(); + account.balance = amount; self.backend.insert_account_info(address, account); Ok(self) @@ -148,16 +150,12 @@ impl Executor { /// Gets the balance of an account pub fn get_balance(&self, address: Address) -> DatabaseResult { - Ok(self - .backend - .basic(h160_to_b160(address))? - .map(|acc| acc.balance.into()) - .unwrap_or_default()) + Ok(self.backend.basic(address)?.map(|acc| acc.balance).unwrap_or_default()) } /// Set the nonce of an account. pub fn set_nonce(&mut self, address: Address, nonce: u64) -> DatabaseResult<&mut Self> { - let mut account = self.backend.basic(h160_to_b160(address))?.unwrap_or_default(); + let mut account = self.backend.basic(address)?.unwrap_or_default(); account.nonce = nonce; self.backend.insert_account_info(address, account); @@ -203,7 +201,7 @@ impl Executor { let from = from.unwrap_or(CALLER); self.backend.set_test_contract(to).set_caller(from); - let res = self.call_committing::<(), _, _>(from, to, "setUp()", (), 0.into(), None)?; + let res = self.call_committing::<(), _, _>(from, to, "setUp()", (), U256::ZERO, None)?; // record any changes made to the block's environment during setup self.env.block = res.env.block.clone(); @@ -266,7 +264,7 @@ impl Executor { calldata: Bytes, value: U256, ) -> eyre::Result { - let env = self.build_test_env(from, TransactTo::Call(h160_to_b160(to)), calldata, value); + let env = self.build_test_env(from, TransactTo::Call(to), calldata, value); let mut result = self.call_raw_with_env(env)?; self.commit(&mut result); Ok(result) @@ -286,12 +284,7 @@ impl Executor { let calldata = Bytes::from(encode_function_data(&func, args)?.to_vec()); // execute the call - let env = self.build_test_env( - from, - TransactTo::Call(h160_to_b160(test_contract)), - calldata, - value, - ); + let env = self.build_test_env(from, TransactTo::Call(test_contract), calldata, value); let call_result = self.call_raw_with_env(env)?; convert_call_result(abi, &func, call_result) } @@ -326,8 +319,7 @@ impl Executor { ) -> eyre::Result { let mut inspector = self.inspector.clone(); // Build VM - let mut env = - self.build_test_env(from, TransactTo::Call(h160_to_b160(to)), calldata, value); + let mut env = self.build_test_env(from, TransactTo::Call(to), calldata, value); let mut db = FuzzBackendWrapper::new(&self.backend); let result = db.inspect_ref(&mut env, &mut inspector)?; @@ -454,19 +446,11 @@ impl Executor { // also mark this library as persistent, this will ensure that the state of the library is // persistent across fork swaps in forking mode - self.backend.add_persistent_account(b160_to_h160(address)); + self.backend.add_persistent_account(address); trace!(address=?address, "deployed contract"); - Ok(DeployResult { - address: b160_to_h160(address), - gas_used, - gas_refunded, - logs, - traces, - debug, - env, - }) + Ok(DeployResult { address, gas_used, gas_refunded, logs, traces, debug, env }) } /// Deploys a contract and commits the new state to the underlying database. @@ -527,7 +511,7 @@ impl Executor { // we only clone the test contract and cheatcode accounts, that's all we need to evaluate // success for addr in [address, CHEATCODE_ADDRESS] { - let acc = self.backend.basic(h160_to_b160(addr))?.unwrap_or_default(); + let acc = self.backend.basic(addr)?.unwrap_or_default(); backend.insert_account_info(addr, acc); } @@ -541,8 +525,14 @@ impl Executor { let mut success = !reverted; if success { // Check if a DSTest assertion failed - let call = - executor.call::(CALLER, address, "failed()(bool)", (), 0.into(), None); + let call = executor.call::( + CALLER, + address, + "failed()(bool)", + (), + U256::ZERO, + None, + ); if let Ok(CallResult { result: failed, .. }) = call { success = !failed; @@ -569,19 +559,19 @@ impl Executor { // network conditions - the actual gas price is kept in `self.block` and is applied by // the cheatcode handler if it is enabled block: BlockEnv { - basefee: rU256::from(0), - gas_limit: self.gas_limit.into(), + basefee: U256::from(0), + gas_limit: self.gas_limit, ..self.env.block.clone() }, tx: TxEnv { - caller: h160_to_b160(caller), + caller, transact_to, data, - value: value.into(), + value, // As above, we set the gas price to 0. - gas_price: rU256::from(0), + gas_price: U256::from(0), gas_priority_fee: None, - gas_limit: self.gas_limit.as_u64(), + gas_limit: self.gas_limit.to(), ..self.env.tx.clone() }, } diff --git a/crates/evm/src/executor/opts.rs b/crates/evm/src/executor/opts.rs index eeef6924f51c4..71c0b1347dbde 100644 --- a/crates/evm/src/executor/opts.rs +++ b/crates/evm/src/executor/opts.rs @@ -1,15 +1,13 @@ -use crate::{ - executor::fork::CreateFork, - utils::{h160_to_b160, h256_to_b256, RuntimeOrHandle}, -}; +use crate::{executor::fork::CreateFork, utils::RuntimeOrHandle}; +use alloy_primitives::{Address, B256, U256}; use ethers::{ providers::{Middleware, Provider}, - types::{Address, Block, Chain, TxHash, H256, U256}, + types::{Block, Chain, TxHash}, }; use eyre::WrapErr; use foundry_common::{self, ProviderBuilder, RpcUrl, ALCHEMY_FREE_TIER_CUPS}; use foundry_config::Config; -use revm::primitives::{BlockEnv, CfgEnv, SpecId, TxEnv, U256 as rU256}; +use revm::primitives::{BlockEnv, CfgEnv, SpecId, TxEnv}; use serde::{Deserialize, Deserializer, Serialize}; use super::fork::environment; @@ -105,19 +103,19 @@ impl EvmOpts { revm::primitives::Env { block: BlockEnv { - number: rU256::from(self.env.block_number), - coinbase: h160_to_b160(self.env.block_coinbase), - timestamp: rU256::from(self.env.block_timestamp), - difficulty: rU256::from(self.env.block_difficulty), - prevrandao: Some(h256_to_b256(self.env.block_prevrandao)), - basefee: rU256::from(self.env.block_base_fee_per_gas), - gas_limit: self.gas_limit().into(), + number: U256::from(self.env.block_number), + coinbase: self.env.block_coinbase, + timestamp: U256::from(self.env.block_timestamp), + difficulty: U256::from(self.env.block_difficulty), + prevrandao: Some(self.env.block_prevrandao), + basefee: U256::from(self.env.block_base_fee_per_gas), + gas_limit: self.gas_limit(), }, cfg, tx: TxEnv { - gas_price: rU256::from(self.env.gas_price.unwrap_or_default()), - gas_limit: self.gas_limit().as_u64(), - caller: h160_to_b160(self.sender), + gas_price: U256::from(self.env.gas_price.unwrap_or_default()), + gas_limit: self.gas_limit().to(), + caller: self.sender, ..Default::default() }, } @@ -144,7 +142,7 @@ impl EvmOpts { /// Returns the gas limit to use pub fn gas_limit(&self) -> U256 { - self.env.block_gas_limit.unwrap_or(self.env.gas_limit).into() + U256::from(self.env.block_gas_limit.unwrap_or(self.env.gas_limit)) } /// Returns the configured chain id, which will be @@ -228,7 +226,7 @@ pub struct Env { pub block_difficulty: u64, /// Previous block beacon chain random value. Before merge this field is used for mix_hash - pub block_prevrandao: H256, + pub block_prevrandao: B256, /// the block.gaslimit value during EVM execution #[serde( diff --git a/crates/evm/src/executor/snapshot.rs b/crates/evm/src/executor/snapshot.rs index a549362b101ae..d931e45f7e145 100644 --- a/crates/evm/src/executor/snapshot.rs +++ b/crates/evm/src/executor/snapshot.rs @@ -1,7 +1,7 @@ //! support for snapshotting different states -use ethers::types::U256; -use std::collections::HashMap; +use alloy_primitives::U256; +use std::{collections::HashMap, ops::Add}; /// Represents all snapshots #[derive(Debug, Clone)] @@ -15,7 +15,7 @@ pub struct Snapshots { impl Snapshots { fn next_id(&mut self) -> U256 { let id = self.id; - self.id = id.saturating_add(U256::one()); + self.id = id.saturating_add(U256::from(1)); id } @@ -32,10 +32,10 @@ impl Snapshots { let snapshot = self.snapshots.remove(&id); // revert all snapshots taken after the snapshot - let mut to_revert = id + 1; + let mut to_revert = id.add(U256::from(1)); while to_revert < self.id { self.snapshots.remove(&to_revert); - to_revert = to_revert + 1; + to_revert += U256::from(1); } snapshot @@ -66,6 +66,6 @@ impl Snapshots { impl Default for Snapshots { fn default() -> Self { - Self { id: U256::zero(), snapshots: HashMap::new() } + Self { id: U256::ZERO, snapshots: HashMap::new() } } } diff --git a/crates/evm/src/fuzz/invariant/error.rs b/crates/evm/src/fuzz/invariant/error.rs index 0f6157d329655..b917a1ca83a08 100644 --- a/crates/evm/src/fuzz/invariant/error.rs +++ b/crates/evm/src/fuzz/invariant/error.rs @@ -4,15 +4,14 @@ use crate::{ executor::{Executor, RawCallResult}, fuzz::{invariant::set_up_inner_replay, *}, trace::{load_contracts, TraceKind, Traces}, + utils::h160_to_b160, CALLER, }; -use ethers::{ - abi::Function, - types::{Address, U256}, -}; +use ethers::abi::Function; use eyre::{Result, WrapErr}; use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact}; use proptest::test_runner::TestError; +use revm::primitives::U256; #[derive(Debug, Clone)] pub struct InvariantFuzzError { @@ -108,7 +107,12 @@ impl InvariantFuzzError { // Replay each call from the sequence until we break the invariant. for (sender, (addr, bytes)) in calls.iter() { let call_result = executor - .call_raw_committing(*sender, *addr, bytes.0.clone(), U256::zero()) + .call_raw_committing( + h160_to_b160(*sender), + h160_to_b160(*addr), + bytes.0.clone().into(), + U256::ZERO, + ) .expect("bad call to evm"); logs.extend(call_result.logs); @@ -134,7 +138,7 @@ impl InvariantFuzzError { // Checks the invariant. if let Some(func) = &self.func { let error_call_result = executor - .call_raw(CALLER, self.addr, func.0.clone(), U256::zero()) + .call_raw(CALLER, h160_to_b160(self.addr), func.0.clone().into(), U256::ZERO) .expect("bad call to evm"); traces.push((TraceKind::Execution, error_call_result.traces.clone().unwrap())); @@ -169,13 +173,18 @@ impl InvariantFuzzError { let (sender, (addr, bytes)) = details; executor - .call_raw_committing(*sender, *addr, bytes.0.clone(), 0.into()) + .call_raw_committing( + h160_to_b160(*sender), + h160_to_b160(*addr), + bytes.0.clone().into(), + U256::ZERO, + ) .expect("bad call to evm"); // Checks the invariant. If we exit before the last call, all the better. if let Some(func) = &self.func { let error_call_result = executor - .call_raw(CALLER, self.addr, func.0.clone(), 0.into()) + .call_raw(CALLER, h160_to_b160(self.addr), func.0.clone().into(), U256::ZERO) .expect("bad call to evm"); if error_call_result.reverted { diff --git a/crates/evm/src/fuzz/invariant/executor.rs b/crates/evm/src/fuzz/invariant/executor.rs index 4a977a934e103..a16a51c224595 100644 --- a/crates/evm/src/fuzz/invariant/executor.rs +++ b/crates/evm/src/fuzz/invariant/executor.rs @@ -16,13 +16,10 @@ use crate::{ }, FuzzCase, FuzzedCases, }, - utils::{get_function, h160_to_b160}, + utils::{b160_to_h160, get_function, h160_to_b160}, CALLER, }; -use ethers::{ - abi::{Abi, Address, Detokenize, FixedBytes, Tokenizable, TokenizableItem}, - prelude::U256, -}; +use ethers::abi::{Abi, Address, Detokenize, FixedBytes, Tokenizable, TokenizableItem}; use eyre::{eyre, ContextCompat, Result}; use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact}; use foundry_config::{FuzzDictionaryConfig, InvariantConfig}; @@ -32,7 +29,7 @@ use proptest::{ test_runner::{TestCaseError, TestRunner}, }; use revm::{ - primitives::{HashMap, B160}, + primitives::{Address as rAddress, HashMap, U256 as rU256}, DatabaseCommit, }; use std::{cell::RefCell, collections::BTreeMap, sync::Arc}; @@ -151,7 +148,12 @@ impl<'a> InvariantExecutor<'a> { // Executes the call from the randomly generated sequence. let call_result = executor - .call_raw(*sender, *address, calldata.0.clone(), U256::zero()) + .call_raw( + h160_to_b160(*sender), + h160_to_b160(*address), + calldata.0.clone().into(), + rU256::ZERO, + ) .expect("could not make raw evm call"); // Collect data for fuzzing from the state changeset. @@ -422,8 +424,8 @@ impl<'a> InvariantExecutor<'a> { .into_iter() .filter(|(addr, (identifier, _))| { *addr != invariant_address && - *addr != CHEATCODE_ADDRESS && - *addr != HARDHAT_CONSOLE_ADDRESS && + *addr != b160_to_h160(CHEATCODE_ADDRESS) && + *addr != b160_to_h160(HARDHAT_CONSOLE_ADDRESS) && (selected.is_empty() || selected.contains(addr)) && (self.artifact_filters.targeted.is_empty() || self.artifact_filters.targeted.contains_key(identifier)) && @@ -565,10 +567,10 @@ impl<'a> InvariantExecutor<'a> { if let Some(func) = abi.functions().find(|func| func.name == method_name) { if let Ok(call_result) = self.executor.call::, _, _>( CALLER, - address, + h160_to_b160(address), func.clone(), (), - U256::zero(), + rU256::ZERO, Some(abi), ) { return call_result.result @@ -588,7 +590,7 @@ impl<'a> InvariantExecutor<'a> { /// before inserting it into the dictionary. Otherwise, we flood the dictionary with /// randomly generated addresses. fn collect_data( - state_changeset: &mut HashMap, + state_changeset: &mut HashMap, sender: &Address, call_result: &RawCallResult, fuzz_state: EvmFuzzState, @@ -634,10 +636,9 @@ fn can_continue( let mut call_results = None; // Detect handler assertion failures first. - let handlers_failed = targeted_contracts - .lock() - .iter() - .any(|contract| !executor.is_success(*contract.0, false, state_changeset.clone(), false)); + let handlers_failed = targeted_contracts.lock().iter().any(|contract| { + !executor.is_success(h160_to_b160(*contract.0), false, state_changeset.clone(), false) + }); // Assert invariants IFF the call did not revert and the handlers did not fail. if !call_result.reverted && !handlers_failed { diff --git a/crates/evm/src/fuzz/invariant/mod.rs b/crates/evm/src/fuzz/invariant/mod.rs index 9bd5a828f0190..38761753ecb72 100644 --- a/crates/evm/src/fuzz/invariant/mod.rs +++ b/crates/evm/src/fuzz/invariant/mod.rs @@ -4,14 +4,16 @@ use crate::{ executor::Executor, fuzz::*, trace::{load_contracts, TraceKind, Traces}, + utils::h160_to_b160, CALLER, }; use ethers::{ abi::{Abi, Function}, - types::{Address, Bytes, U256}, + types::{Address, Bytes}, }; use foundry_common::ContractsByArtifact; use parking_lot::Mutex; +use revm::primitives::U256; use std::{collections::BTreeMap, sync::Arc}; pub use proptest::test_runner::Config as FuzzConfig; @@ -67,16 +69,16 @@ pub fn assert_invariants( let mut call_result = executor .call_raw( CALLER, - invariant_contract.address, + h160_to_b160(invariant_contract.address), func.encode_input(&[]).expect("invariant should have no inputs").into(), - U256::zero(), + U256::ZERO, ) .expect("EVM error"); // This will panic and get caught by the executor let is_err = call_result.reverted || !executor.is_success( - invariant_contract.address, + h160_to_b160(invariant_contract.address), call_result.reverted, call_result.state_changeset.take().expect("we should have a state changeset"), false, @@ -119,7 +121,12 @@ pub fn replay_run( // Replay each call from the sequence until we break the invariant. for (sender, (addr, bytes)) in inputs.iter() { let call_result = executor - .call_raw_committing(*sender, *addr, bytes.0.clone(), U256::zero()) + .call_raw_committing( + h160_to_b160(*sender), + h160_to_b160(*addr), + bytes.0.clone().into(), + U256::ZERO, + ) .expect("bad call to evm"); logs.extend(call_result.logs); @@ -135,9 +142,9 @@ pub fn replay_run( let error_call_result = executor .call_raw( CALLER, - invariant_contract.address, + h160_to_b160(invariant_contract.address), func.encode_input(&[]).expect("invariant should have no inputs").into(), - U256::zero(), + U256::ZERO, ) .expect("bad call to evm"); diff --git a/crates/evm/src/fuzz/mod.rs b/crates/evm/src/fuzz/mod.rs index f704a0696f88c..9ff21ef33b791 100644 --- a/crates/evm/src/fuzz/mod.rs +++ b/crates/evm/src/fuzz/mod.rs @@ -1,9 +1,12 @@ +//! Executor wrapper which can be used for fuzzing, using [`proptest`](https://docs.rs/proptest/1.0.0/proptest/) use crate::{ coverage::HitMaps, decode::{self, decode_console_logs}, executor::{Executor, RawCallResult}, trace::CallTraceArena, + utils::{b160_to_h160, h160_to_b160}, }; +use alloy_primitives::U256; use error::{FuzzError, ASSUME_MAGIC_RETURN_CODE}; use ethers::{ abi::{Abi, Function, Token}, @@ -149,7 +152,7 @@ impl<'a> FuzzedExecutor<'a> { counterexample: None, decoded_logs: decode_console_logs(&call.logs), logs: call.logs, - labeled_addresses: call.labels, + labeled_addresses: call.labels.into_iter().map(|l| (b160_to_h160(l.0), l.1)).collect(), traces: if run_result.is_ok() { traces.into_inner() } else { call.traces.clone() }, coverage: coverage.into_inner(), }; @@ -198,7 +201,12 @@ impl<'a> FuzzedExecutor<'a> { ) -> Result { let call = self .executor - .call_raw(self.sender, address, calldata.0.clone(), 0.into()) + .call_raw( + h160_to_b160(self.sender), + h160_to_b160(address), + calldata.0.clone().into(), + U256::ZERO, + ) .map_err(|_| TestCaseError::fail(FuzzError::FailedContractCall))?; let state_changeset = call .state_changeset @@ -223,8 +231,12 @@ impl<'a> FuzzedExecutor<'a> { .as_ref() .map_or_else(Default::default, |cheats| cheats.breakpoints.clone()); - let success = - self.executor.is_success(address, call.reverted, state_changeset.clone(), should_fail); + let success = self.executor.is_success( + h160_to_b160(address), + call.reverted, + state_changeset.clone(), + should_fail, + ); if success { Ok(FuzzOutcome::Case(CaseOutcome { diff --git a/crates/evm/src/fuzz/strategies/state.rs b/crates/evm/src/fuzz/strategies/state.rs index ba62a0eb22564..7a8439b36da9e 100644 --- a/crates/evm/src/fuzz/strategies/state.rs +++ b/crates/evm/src/fuzz/strategies/state.rs @@ -100,7 +100,7 @@ pub fn build_initial_state( let mut state = FuzzDictionary::default(); for (address, account) in db.accounts.iter() { - let address: Address = (*address).into(); + let address: Address = b160_to_h160(*address); // Insert basic account information state.values_mut().insert(H256::from(address).into()); @@ -108,7 +108,7 @@ pub fn build_initial_state( if config.include_push_bytes { if let Some(code) = &account.info.code { if state.addresses_mut().insert(address) { - for push_byte in collect_push_bytes(code.bytes().clone()) { + for push_byte in collect_push_bytes(code.bytes().clone().0) { state.values_mut().insert(push_byte); } } @@ -118,8 +118,8 @@ pub fn build_initial_state( if config.include_storage { // Insert storage for (slot, value) in &account.storage { - let slot = (*slot).into(); - let value = (*value).into(); + let slot = ru256_to_u256(*slot); + let value = ru256_to_u256(*value); state.values_mut().insert(utils::u256_to_h256_be(slot).into()); state.values_mut().insert(utils::u256_to_h256_be(value).into()); // also add the value below and above the storage value to the dictionary. @@ -164,7 +164,7 @@ pub fn collect_state_from_call( // Insert push bytes if let Some(code) = &account.info.code { if state.addresses_mut().insert(b160_to_h160(*address)) { - for push_byte in collect_push_bytes(code.bytes().clone()) { + for push_byte in collect_push_bytes(code.bytes().clone().0) { state.values_mut().insert(push_byte); } } @@ -174,7 +174,7 @@ pub fn collect_state_from_call( if config.include_storage && state.state_values.len() < config.max_fuzz_dictionary_values { // Insert storage for (slot, value) in &account.storage { - let slot = (*slot).into(); + let slot = ru256_to_u256(*slot); let value = ru256_to_u256(value.present_value()); state.values_mut().insert(utils::u256_to_h256_be(slot).into()); state.values_mut().insert(utils::u256_to_h256_be(value).into()); diff --git a/crates/evm/src/lib.rs b/crates/evm/src/lib.rs index 1d4d04ce89ad1..f39abbfe1fdf5 100644 --- a/crates/evm/src/lib.rs +++ b/crates/evm/src/lib.rs @@ -19,7 +19,7 @@ pub mod coverage; /// Forge test execution backends pub mod executor; -use ethers::types::{ActionType, CallType, H160}; +use ethers::types::{ActionType, CallType}; pub use executor::abi; /// Fuzzing wrapper for executors @@ -32,7 +32,10 @@ pub mod utils; pub use ethers::types::Address; pub use hashbrown; use revm::interpreter::{CallScheme, CreateScheme}; -pub use revm::{self, primitives::HashMap}; +pub use revm::{ + self, + primitives::{Address as aB160, HashMap}, +}; use serde::{Deserialize, Serialize}; /// Stores the caller address to be used as _sender_ account for: @@ -41,13 +44,13 @@ use serde::{Deserialize, Serialize}; /// /// The address was derived from `address(uint160(uint256(keccak256("foundry default caller"))))` /// and is equal to 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38. -pub const CALLER: Address = H160([ +pub const CALLER: aB160 = aB160::new([ 0x18, 0x04, 0xc8, 0xAB, 0x1F, 0x12, 0xE6, 0xbb, 0xF3, 0x89, 0x4D, 0x40, 0x83, 0xF3, 0x3E, 0x07, 0x30, 0x9D, 0x1F, 0x38, ]); /// Stores the default test contract address: 0xb4c79daB8f259C7Aee6E5b2Aa729821864227e84 -pub const TEST_CONTRACT_ADDRESS: Address = H160([ +pub const TEST_CONTRACT_ADDRESS: aB160 = aB160::new([ 180, 199, 157, 171, 143, 37, 156, 122, 238, 110, 91, 42, 167, 41, 130, 24, 100, 34, 126, 132, ]); diff --git a/crates/evm/src/trace/decoder.rs b/crates/evm/src/trace/decoder.rs index 39c00e38a4d69..11db65c2fca10 100644 --- a/crates/evm/src/trace/decoder.rs +++ b/crates/evm/src/trace/decoder.rs @@ -7,6 +7,7 @@ use crate::{ decode, executor::inspector::DEFAULT_CREATE2_DEPLOYER, trace::{node::CallTraceNode, utils}, + utils::b160_to_h160, CALLER, TEST_CONTRACT_ADDRESS, }; use ethers::{ @@ -156,11 +157,11 @@ impl CallTraceDecoder { contracts: Default::default(), labels: [ - (CHEATCODE_ADDRESS, "VM".to_string()), - (HARDHAT_CONSOLE_ADDRESS, "console".to_string()), - (DEFAULT_CREATE2_DEPLOYER, "Create2Deployer".to_string()), - (CALLER, "DefaultSender".to_string()), - (TEST_CONTRACT_ADDRESS, "DefaultTestContract".to_string()), + (b160_to_h160(CHEATCODE_ADDRESS), "VM".to_string()), + (b160_to_h160(HARDHAT_CONSOLE_ADDRESS), "console".to_string()), + (b160_to_h160(DEFAULT_CREATE2_DEPLOYER), "Create2Deployer".to_string()), + (b160_to_h160(CALLER), "DefaultSender".to_string()), + (b160_to_h160(TEST_CONTRACT_ADDRESS), "DefaultTestContract".to_string()), ] .into(), @@ -256,7 +257,7 @@ impl CallTraceDecoder { if bytes.len() >= 4 { if let Some(funcs) = self.functions.get(&bytes[..SELECTOR_LEN]) { node.decode_function(funcs, &self.labels, &self.errors, self.verbosity); - } else if node.trace.address == DEFAULT_CREATE2_DEPLOYER { + } else if node.trace.address == b160_to_h160(DEFAULT_CREATE2_DEPLOYER) { node.trace.data = RawOrDecodedCall::Decoded("create2".to_string(), String::new(), vec![]); } else if let Some(identifier) = &self.signature_identifier { diff --git a/crates/evm/src/trace/mod.rs b/crates/evm/src/trace/mod.rs index af490b6448c8d..5b7365333d7c6 100644 --- a/crates/evm/src/trace/mod.rs +++ b/crates/evm/src/trace/mod.rs @@ -1,5 +1,9 @@ use crate::{ - abi::CHEATCODE_ADDRESS, debug::Instruction, trace::identifier::LocalTraceIdentifier, CallKind, + abi::CHEATCODE_ADDRESS, + debug::Instruction, + trace::identifier::LocalTraceIdentifier, + utils::{b160_to_h160, ru256_to_u256}, + CallKind, }; pub use decoder::{CallTraceDecoder, CallTraceDecoderBuilder}; use ethers::{ @@ -429,7 +433,7 @@ impl From<&CallTraceStep> for StructLog { } else { None }, - stack: Some(step.stack.data().iter().copied().map(|data| data.into()).collect()), + stack: Some(step.stack.data().iter().copied().map(ru256_to_u256).collect()), // Filled in `CallTraceArena::geth_trace` as a result of compounding all slot changes storage: None, } @@ -596,7 +600,7 @@ impl TraceKind { /// Chooses the color of the trace depending on the destination address and status of the call. fn trace_color(trace: &CallTrace) -> Color { - if trace.address == CHEATCODE_ADDRESS { + if trace.address == b160_to_h160(CHEATCODE_ADDRESS) { Color::Blue } else if trace.success { Color::Green diff --git a/crates/evm/src/trace/node.rs b/crates/evm/src/trace/node.rs index be0c55162a113..7b9a2930e9c02 100644 --- a/crates/evm/src/trace/node.rs +++ b/crates/evm/src/trace/node.rs @@ -5,6 +5,7 @@ use crate::{ utils, utils::decode_cheatcode_outputs, CallTrace, LogCallOrder, RawOrDecodedCall, RawOrDecodedLog, RawOrDecodedReturnData, }, + utils::b160_to_h160, CallKind, }; use ethers::{ @@ -109,7 +110,7 @@ impl CallTraceNode { if let RawOrDecodedCall::Raw(ref bytes) = self.trace.data { let inputs = if bytes.len() >= SELECTOR_LEN { - if self.trace.address == CHEATCODE_ADDRESS { + if self.trace.address == b160_to_h160(CHEATCODE_ADDRESS) { // Try to decode cheatcode inputs in a more custom way utils::decode_cheatcode_inputs(func, bytes, errors, verbosity).unwrap_or_else( || { @@ -136,7 +137,7 @@ impl CallTraceNode { if let RawOrDecodedReturnData::Raw(bytes) = &self.trace.output { if !bytes.is_empty() && self.trace.success { - if self.trace.address == CHEATCODE_ADDRESS { + if self.trace.address == b160_to_h160(CHEATCODE_ADDRESS) { if let Some(decoded) = funcs .iter() .find_map(|func| decode_cheatcode_outputs(func, bytes, verbosity)) diff --git a/crates/evm/src/utils.rs b/crates/evm/src/utils.rs index 23f83b2640850..ad0b0851e5dc2 100644 --- a/crates/evm/src/utils.rs +++ b/crates/evm/src/utils.rs @@ -1,6 +1,6 @@ use ethers::{ abi::{Abi, FixedBytes, Function}, - types::{Block, Chain, H256, U256}, + types::{Block, Chain, H160, H256, U256}, }; use eyre::ContextCompat; use revm::{ @@ -39,14 +39,14 @@ pub fn h256_to_u256_le(storage: H256) -> U256 { /// Small helper function to convert revm's [B160] into ethers's [H160]. #[inline] -pub fn b160_to_h160(b: revm::primitives::B160) -> ethers::types::H160 { - ethers::types::H160(b.0) +pub fn b160_to_h160(b: alloy_primitives::Address) -> ethers::types::H160 { + H160::from_slice(b.as_slice()) } /// Small helper function to convert ethers's [H160] into revm's [B160]. #[inline] -pub fn h160_to_b160(h: ethers::types::H160) -> revm::primitives::B160 { - revm::primitives::B160(h.0) +pub fn h160_to_b160(h: ethers::types::H160) -> alloy_primitives::Address { + alloy_primitives::Address::from_slice(h.as_bytes()) } /// Small helper function to convert revm's [B256] into ethers's [H256]. @@ -57,8 +57,8 @@ pub fn b256_to_h256(b: revm::primitives::B256) -> ethers::types::H256 { /// Small helper function to convert ether's [H256] into revm's [B256]. #[inline] -pub fn h256_to_b256(h: ethers::types::H256) -> revm::primitives::B256 { - revm::primitives::B256(h.0) +pub fn h256_to_b256(h: ethers::types::H256) -> alloy_primitives::B256 { + alloy_primitives::B256::from_slice(h.as_bytes()) } /// Small helper function to convert ether's [U256] into revm's [U256]. @@ -69,9 +69,15 @@ pub fn u256_to_ru256(u: ethers::types::U256) -> revm::primitives::U256 { revm::primitives::U256::from_le_bytes(buffer) } +// Small helper function to convert ethers's [U64] into alloy's [U64]. +#[inline] +pub fn u64_to_ru64(u: ethers::types::U64) -> alloy_primitives::U64 { + alloy_primitives::U64::from(u.as_u64()) +} + /// Small helper function to convert revm's [U256] into ethers's [U256]. #[inline] -pub fn ru256_to_u256(u: revm::primitives::U256) -> ethers::types::U256 { +pub fn ru256_to_u256(u: alloy_primitives::U256) -> ethers::types::U256 { ethers::types::U256::from_little_endian(&u.as_le_bytes()) } @@ -139,7 +145,7 @@ pub fn apply_chain_and_block_specific_env_changes( // `l1BlockNumber` field if let Some(l1_block_number) = block.other.get("l1BlockNumber").cloned() { if let Ok(l1_block_number) = serde_json::from_value::(l1_block_number) { - env.block.number = l1_block_number.into(); + env.block.number = u256_to_ru256(l1_block_number); } } } diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index e52b800c837ed..272b4625ea2c0 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -39,6 +39,8 @@ forge-doc.workspace = true foundry-cli.workspace = true foundry-debugger.workspace = true +alloy-primitives = { workspace = true, default-features = false, features = ["std", "serde"] } + async-trait = "0.1" bytes = "1.4" clap = { version = "4", features = ["derive", "env", "unicode", "wrap_help"] } diff --git a/crates/forge/bin/cmd/coverage.rs b/crates/forge/bin/cmd/coverage.rs index 0ce7fdbc40f1a..473cb59ba8a2b 100644 --- a/crates/forge/bin/cmd/coverage.rs +++ b/crates/forge/bin/cmd/coverage.rs @@ -27,6 +27,7 @@ use foundry_cli::{ }; use foundry_common::{compile::ProjectCompiler, evm::EvmArgs, fs}; use foundry_config::{Config, SolcReq}; +use foundry_evm::utils::{b160_to_h160, ru256_to_u256}; use semver::Version; use std::{collections::HashMap, sync::mpsc::channel}; use tracing::trace; @@ -287,9 +288,9 @@ impl CoverageArgs { // Build the contract runner let env = evm_opts.evm_env().await?; let mut runner = MultiContractRunnerBuilder::default() - .initial_balance(evm_opts.initial_balance) + .initial_balance(ru256_to_u256(evm_opts.initial_balance)) .evm_spec(config.evm_spec_id()) - .sender(evm_opts.sender) + .sender(b160_to_h160(evm_opts.sender)) .with_fork(evm_opts.get_fork(&config, env.clone())) .with_cheats_config(CheatsConfig::new(&config, &evm_opts)) .with_test_options(TestOptions { fuzz: config.fuzz, ..Default::default() }) diff --git a/crates/forge/bin/cmd/script/build.rs b/crates/forge/bin/cmd/script/build.rs index 1ed67955aba11..aee3846933c87 100644 --- a/crates/forge/bin/cmd/script/build.rs +++ b/crates/forge/bin/cmd/script/build.rs @@ -16,6 +16,7 @@ use foundry_common::{ compact_to_contract, compile::{self, ContractSources}, }; +use foundry_evm::utils::b160_to_h160; use foundry_utils::{PostLinkInput, ResolvedDependency}; use std::{collections::BTreeMap, fs, str::FromStr}; use tracing::{trace, warn}; @@ -64,7 +65,7 @@ impl ScriptArgs { project, contracts, script_config.config.parsed_libraries()?, - script_config.evm_opts.sender, + b160_to_h160(script_config.evm_opts.sender), script_config.sender_nonce, )?; diff --git a/crates/forge/bin/cmd/script/cmd.rs b/crates/forge/bin/cmd/script/cmd.rs index 93aab18eac3dd..8c602180f247a 100644 --- a/crates/forge/bin/cmd/script/cmd.rs +++ b/crates/forge/bin/cmd/script/cmd.rs @@ -7,6 +7,7 @@ use eyre::Result; use foundry_cli::utils::LoadConfig; use foundry_common::{contracts::flatten_contracts, try_get_http_provider}; use foundry_debugger::DebuggerArgs; +use foundry_evm::utils::b160_to_h160; use std::sync::Arc; use tracing::trace; @@ -32,8 +33,12 @@ impl ScriptArgs { if let Some(ref fork_url) = script_config.evm_opts.fork_url { // when forking, override the sender's nonce to the onchain value - script_config.sender_nonce = - foundry_utils::next_nonce(script_config.evm_opts.sender, fork_url, None).await? + script_config.sender_nonce = foundry_utils::next_nonce( + b160_to_h160(script_config.evm_opts.sender), + fork_url, + None, + ) + .await? } else { // if not forking, then ignore any pre-deployed library addresses script_config.config.libraries = Default::default(); @@ -65,8 +70,9 @@ impl ScriptArgs { // We need to execute the script even if just resuming, in case we need to collect private // keys from the execution. - let mut result = - self.execute(&mut script_config, contract, sender, &predeploy_libraries).await?; + let mut result = self + .execute(&mut script_config, contract, b160_to_h160(sender), &predeploy_libraries) + .await?; if self.resume || (self.verify && !self.broadcast) { return self @@ -160,7 +166,7 @@ impl ScriptArgs { // Add predeploy libraries to the list of broadcastable transactions. let mut lib_deploy = self.create_deploy_transactions( - script_config.evm_opts.sender, + b160_to_h160(script_config.evm_opts.sender), script_config.sender_nonce, &predeploy_libraries, &script_config.evm_opts.fork_url, @@ -350,7 +356,7 @@ impl ScriptArgs { } if let Some(wallets) = self.wallets.private_keys()? { if wallets.len() == 1 { - script_config.evm_opts.sender = wallets.get(0).unwrap().address() + script_config.evm_opts.sender = h160_to_b160(wallets.get(0).unwrap().address()) } } Ok(()) diff --git a/crates/forge/bin/cmd/script/executor.rs b/crates/forge/bin/cmd/script/executor.rs index d084c8caa7053..39915a8b3d421 100644 --- a/crates/forge/bin/cmd/script/executor.rs +++ b/crates/forge/bin/cmd/script/executor.rs @@ -20,6 +20,7 @@ use forge::{ }; use foundry_cli::utils::{ensure_clean_constructor, needs_setup}; use foundry_common::{shell, RpcUrl}; +use foundry_evm::utils::{b160_to_h160, ru256_to_u256}; use futures::future::join_all; use parking_lot::RwLock; use std::{collections::VecDeque, sync::Arc}; @@ -261,7 +262,12 @@ impl ScriptArgs { ( rpc.clone(), - self.prepare_runner(&mut script_config, sender, SimulationStage::OnChain).await, + self.prepare_runner( + &mut script_config, + b160_to_h160(sender), + SimulationStage::OnChain, + ) + .await, ) }) .collect::>(); @@ -316,6 +322,10 @@ impl ScriptArgs { }); } - ScriptRunner::new(builder.build(env, db), script_config.evm_opts.initial_balance, sender) + ScriptRunner::new( + builder.build(env, db), + ru256_to_u256(script_config.evm_opts.initial_balance), + sender, + ) } } diff --git a/crates/forge/bin/cmd/script/mod.rs b/crates/forge/bin/cmd/script/mod.rs index 519b35da2d570..693eed7dad0a8 100644 --- a/crates/forge/bin/cmd/script/mod.rs +++ b/crates/forge/bin/cmd/script/mod.rs @@ -50,6 +50,7 @@ use foundry_evm::{ cheatcodes::{util::BroadcastableTransactions, BroadcastableTransaction}, DEFAULT_CREATE2_DEPLOYER, }, + utils::h160_to_b160, }; use futures::future; use serde::{Deserialize, Serialize}; @@ -405,7 +406,7 @@ impl ScriptArgs { shell::println("You have more than one deployer who could predeploy libraries. Using `--sender` instead.")?; return Ok(None) } - } else if sender != evm_opts.sender { + } else if h160_to_b160(sender) != evm_opts.sender { new_sender = Some(sender); } } @@ -550,7 +551,7 @@ impl ScriptArgs { // Find if it's a CREATE or CREATE2. Otherwise, skip transaction. if let Some(NameOrAddress::Address(to)) = to { - if *to == DEFAULT_CREATE2_DEPLOYER { + if h160_to_b160(*to) == DEFAULT_CREATE2_DEPLOYER { // Size of the salt prefix. offset = 32; } diff --git a/crates/forge/bin/cmd/script/runner.rs b/crates/forge/bin/cmd/script/runner.rs index 1781d9f9f5d57..e088a222f1a3f 100644 --- a/crates/forge/bin/cmd/script/runner.rs +++ b/crates/forge/bin/cmd/script/runner.rs @@ -3,10 +3,14 @@ use ethers::types::{Address, Bytes, NameOrAddress, U256}; use eyre::Result; use forge::{ executor::{CallResult, DeployResult, EvmError, ExecutionErr, Executor, RawCallResult}, - revm::interpreter::{return_ok, InstructionResult}, + revm::{ + interpreter::{return_ok, InstructionResult}, + primitives::U256 as rU256, + }, trace::{TraceKind, Traces}, CALLER, }; +use foundry_evm::utils::{b160_to_h160, u256_to_ru256}; use tracing::log::trace; /// Represents which simulation stage is the script execution at. @@ -43,7 +47,7 @@ impl ScriptRunner { if !is_broadcast { if self.sender == Config::DEFAULT_SENDER { // We max out their balance so that they can deploy and make calls. - self.executor.set_balance(self.sender, U256::MAX)?; + self.executor.set_balance(h160_to_b160(self.sender), rU256::MAX)?; } if need_create2_deployer { @@ -51,10 +55,10 @@ impl ScriptRunner { } } - self.executor.set_nonce(self.sender, sender_nonce.as_u64())?; + self.executor.set_nonce(h160_to_b160(self.sender), sender_nonce.as_u64())?; // We max out their balance so that they can deploy and make calls. - self.executor.set_balance(CALLER, U256::MAX)?; + self.executor.set_balance(CALLER, rU256::MAX)?; // Deploy libraries let mut traces: Traces = libraries @@ -62,7 +66,7 @@ impl ScriptRunner { .filter_map(|code| { let DeployResult { traces, .. } = self .executor - .deploy(self.sender, code.0.clone(), 0u32.into(), None) + .deploy(h160_to_b160(self.sender), code.0.clone().into(), rU256::ZERO, None) .expect("couldn't deploy library"); traces @@ -79,11 +83,11 @@ impl ScriptRunner { .. } = self .executor - .deploy(CALLER, code.0, 0u32.into(), None) + .deploy(CALLER, code.0.into(), rU256::ZERO, None) .map_err(|err| eyre::eyre!("Failed to deploy script:\n{}", err))?; traces.extend(constructor_traces.map(|traces| (TraceKind::Deployment, traces))); - self.executor.set_balance(address, self.initial_balance)?; + self.executor.set_balance(address, u256_to_ru256(self.initial_balance))?; // Optionally call the `setUp` function let (success, gas_used, labeled_addresses, transactions, debug, script_wallets) = if !setup @@ -98,7 +102,7 @@ impl ScriptRunner { vec![], ) } else { - match self.executor.setup(Some(self.sender), address) { + match self.executor.setup(Some(h160_to_b160(self.sender)), address) { Ok(CallResult { reverted, traces: setup_traces, @@ -155,12 +159,15 @@ impl ScriptRunner { }; Ok(( - address, + b160_to_h160(address), ScriptResult { returned: bytes::Bytes::new(), success, gas_used, - labeled_addresses, + labeled_addresses: labeled_addresses + .into_iter() + .map(|l| (b160_to_h160(l.0), l.1)) + .collect::>(), transactions, logs, traces, @@ -182,8 +189,10 @@ impl ScriptRunner { ) -> Result<()> { if let Some(cheatcodes) = &self.executor.inspector.cheatcodes { if !cheatcodes.corrected_nonce { - self.executor - .set_nonce(self.sender, sender_initial_nonce.as_u64() + libraries_len as u64)?; + self.executor.set_nonce( + h160_to_b160(self.sender), + sender_initial_nonce.as_u64() + libraries_len as u64, + )?; } self.executor.inspector.cheatcodes.as_mut().unwrap().corrected_nonce = false; } @@ -207,13 +216,13 @@ impl ScriptRunner { self.call(from, to, calldata.unwrap_or_default(), value.unwrap_or(U256::zero()), true) } else if to.is_none() { let (address, gas_used, logs, traces, debug) = match self.executor.deploy( - from, - calldata.expect("No data for create transaction").0, - value.unwrap_or(U256::zero()), + h160_to_b160(from), + calldata.expect("No data for create transaction").0.into(), + u256_to_ru256(value.unwrap_or(U256::zero())), None, ) { Ok(DeployResult { address, gas_used, logs, traces, debug, .. }) => { - (address, gas_used, logs, traces, debug) + (b160_to_h160(address), gas_used, logs, traces, debug) } Err(EvmError::Execution(err)) => { let ExecutionErr { reason, traces, gas_used, logs, debug, .. } = *err; @@ -259,7 +268,12 @@ impl ScriptRunner { value: U256, commit: bool, ) -> Result { - let mut res = self.executor.call_raw(from, to, calldata.0.clone(), value)?; + let mut res = self.executor.call_raw( + h160_to_b160(from), + h160_to_b160(to), + calldata.0.clone().into(), + u256_to_ru256(value), + )?; let mut gas_used = res.gas_used; // We should only need to calculate realistic gas costs when preparing to broadcast @@ -269,7 +283,12 @@ impl ScriptRunner { // Otherwise don't re-execute, or some usecases might be broken: https://github.com/foundry-rs/foundry/issues/3921 if commit { gas_used = self.search_optimal_gas_usage(&res, from, to, &calldata, value)?; - res = self.executor.call_raw_committing(from, to, calldata.0, value)?; + res = self.executor.call_raw_committing( + h160_to_b160(from), + h160_to_b160(to), + calldata.0.into(), + u256_to_ru256(value), + )?; } let RawCallResult { @@ -286,7 +305,7 @@ impl ScriptRunner { let breakpoints = res.cheatcodes.map(|cheats| cheats.breakpoints).unwrap_or_default(); Ok(ScriptResult { - returned: result, + returned: result.0, success: !reverted, gas_used, logs, @@ -298,7 +317,7 @@ impl ScriptRunner { }) .unwrap_or_default(), debug: vec![debug].into_iter().collect(), - labeled_addresses: labels, + labeled_addresses: labels.into_iter().map(|l| (b160_to_h160(l.0), l.1)).collect(), transactions, address: None, script_wallets, @@ -331,7 +350,12 @@ impl ScriptRunner { while (highest_gas_limit - lowest_gas_limit) > 1 { let mid_gas_limit = (highest_gas_limit + lowest_gas_limit) / 2; self.executor.env.tx.gas_limit = mid_gas_limit; - let res = self.executor.call_raw(from, to, calldata.0.clone(), value)?; + let res = self.executor.call_raw( + h160_to_b160(from), + h160_to_b160(to), + calldata.0.clone().into(), + u256_to_ru256(value), + )?; match res.exit_reason { InstructionResult::Revert | InstructionResult::OutOfGas | diff --git a/crates/forge/bin/cmd/script/transaction.rs b/crates/forge/bin/cmd/script/transaction.rs index 73d466f3a460b..2190a835ab4f5 100644 --- a/crates/forge/bin/cmd/script/transaction.rs +++ b/crates/forge/bin/cmd/script/transaction.rs @@ -8,7 +8,8 @@ use ethers::{ use eyre::{ContextCompat, Result, WrapErr}; use foundry_common::{abi::format_token_raw, RpcUrl, SELECTOR_LEN}; use foundry_evm::{ - executor::inspector::DEFAULT_CREATE2_DEPLOYER, trace::CallTraceDecoder, CallKind, + executor::inspector::DEFAULT_CREATE2_DEPLOYER, trace::CallTraceDecoder, utils::h160_to_b160, + CallKind, }; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -76,7 +77,7 @@ impl TransactionWithMetadata { // Specify if any contract was directly created with this transaction if let Some(NameOrAddress::Address(to)) = metadata.transaction.to().cloned() { - if to == DEFAULT_CREATE2_DEPLOYER { + if h160_to_b160(to) == DEFAULT_CREATE2_DEPLOYER { metadata.set_create( true, Address::from_slice(&result.returned), diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 9b44267a432e9..83e528bf1908a 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -32,7 +32,10 @@ use foundry_config::{ get_available_profiles, Config, }; use foundry_debugger::DebuggerArgs; -use foundry_evm::fuzz::CounterExample; +use foundry_evm::{ + fuzz::CounterExample, + utils::{b160_to_h160, ru256_to_u256}, +}; use regex::Regex; use std::{collections::BTreeMap, fs, sync::mpsc::channel, time::Duration}; use tracing::trace; @@ -183,9 +186,9 @@ impl TestArgs { let mut runner_builder = MultiContractRunnerBuilder::default() .set_debug(should_debug) - .initial_balance(evm_opts.initial_balance) + .initial_balance(ru256_to_u256(evm_opts.initial_balance)) .evm_spec(config.evm_spec_id()) - .sender(evm_opts.sender) + .sender(b160_to_h160(evm_opts.sender)) .with_fork(evm_opts.get_fork(&config, env.clone())) .with_cheats_config(CheatsConfig::new(&config, &evm_opts)) .with_test_options(test_options.clone()); diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index d610a19190a68..24d335ab33b71 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -5,6 +5,7 @@ use crate::{ use comfy_table::{presets::ASCII_MARKDOWN, *}; use ethers::types::U256; use foundry_common::{calc, TestFunctionExt}; +use foundry_evm::utils::b160_to_h160; use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, fmt::Display}; @@ -46,7 +47,9 @@ impl GasReport { let node = &arena.arena[node_index]; let trace = &node.trace; - if trace.address == CHEATCODE_ADDRESS || trace.address == HARDHAT_CONSOLE_ADDRESS { + if trace.address == b160_to_h160(CHEATCODE_ADDRESS) || + trace.address == b160_to_h160(HARDHAT_CONSOLE_ADDRESS) + { return } diff --git a/crates/forge/src/multi_runner.rs b/crates/forge/src/multi_runner.rs index ad2c2846f413d..32ebcd8fed5ca 100644 --- a/crates/forge/src/multi_runner.rs +++ b/crates/forge/src/multi_runner.rs @@ -13,6 +13,7 @@ use foundry_evm::{ ExecutorBuilder, }, revm, + utils::{b160_to_h160, ru256_to_u256}, }; use foundry_utils::{PostLinkInput, ResolvedDependency}; use rayon::prelude::*; @@ -207,7 +208,7 @@ impl MultiContractRunner { executor, contract, deploy_code, - self.evm_opts.initial_balance, + ru256_to_u256(self.evm_opts.initial_balance), self.sender, self.errors.as_ref(), libs, @@ -285,7 +286,7 @@ impl MultiContractRunnerBuilder { ArtifactContracts::from_iter(contracts), &mut known_contracts, Default::default(), - evm_opts.sender, + b160_to_h160(evm_opts.sender), U256::one(), &mut deployable_contracts, |post_link_input| { diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index bd80de843c6c0..a7fccef0f9377 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -9,6 +9,7 @@ use foundry_evm::{ executor::EvmError, fuzz::{types::FuzzCase, CounterExample}, trace::{TraceKind, Traces}, + utils::b160_to_h160, }; use serde::{Deserialize, Serialize}; use std::{collections::BTreeMap, fmt, time::Duration}; @@ -244,7 +245,7 @@ impl TestSetup { // force the tracekind to be setup so a trace is shown. traces.extend(err.traces.map(|traces| (TraceKind::Setup, traces))); logs.extend(err.logs); - labeled_addresses.extend(err.labels); + labeled_addresses.extend(err.labels.into_iter().map(|l| (b160_to_h160(l.0), l.1))); Self::failed_with(logs, traces, labeled_addresses, err.reason) } e => Self::failed_with( diff --git a/crates/forge/src/runner.rs b/crates/forge/src/runner.rs index 1d1bd5e13ded0..d48138eabecb2 100644 --- a/crates/forge/src/runner.rs +++ b/crates/forge/src/runner.rs @@ -2,6 +2,7 @@ use crate::{ result::{SuiteResult, TestKind, TestResult, TestSetup, TestStatus}, TestFilter, TestOptions, }; +use alloy_primitives::U256 as rU256; use ethers::{ abi::{Abi, Function}, types::{Address, Bytes, U256}, @@ -24,6 +25,7 @@ use foundry_evm::{ CounterExample, FuzzedExecutor, }, trace::{load_contracts, TraceKind}, + utils::{b160_to_h160, h160_to_b160, u256_to_ru256}, CALLER, }; use proptest::test_runner::{TestError, TestRunner}; @@ -96,17 +98,22 @@ impl<'a> ContractRunner<'a> { trace!(?setup, "Setting test contract"); // We max out their balance so that they can deploy and make calls. - self.executor.set_balance(self.sender, U256::MAX)?; - self.executor.set_balance(CALLER, U256::MAX)?; + self.executor.set_balance(h160_to_b160(self.sender), rU256::MAX)?; + self.executor.set_balance(CALLER, rU256::MAX)?; // We set the nonce of the deployer accounts to 1 to get the same addresses as DappTools - self.executor.set_nonce(self.sender, 1)?; + self.executor.set_nonce(h160_to_b160(self.sender), 1)?; // Deploy libraries let mut logs = Vec::new(); let mut traces = Vec::with_capacity(self.predeploy_libs.len()); for code in self.predeploy_libs.iter() { - match self.executor.deploy(self.sender, code.0.clone(), 0u32.into(), self.errors) { + match self.executor.deploy( + h160_to_b160(self.sender), + code.0.clone().into(), + rU256::ZERO, + self.errors, + ) { Ok(d) => { logs.extend(d.logs); traces.extend(d.traces.map(|traces| (TraceKind::Deployment, traces))); @@ -119,9 +126,9 @@ impl<'a> ContractRunner<'a> { // Deploy the test contract let address = match self.executor.deploy( - self.sender, - self.code.0.clone(), - 0u32.into(), + h160_to_b160(self.sender), + self.code.0.clone().into(), + rU256::ZERO, self.errors, ) { Ok(d) => { @@ -136,9 +143,10 @@ impl<'a> ContractRunner<'a> { // Now we set the contracts initial balance, and we also reset `self.sender`s and `CALLER`s // balance to the initial balance we want - self.executor.set_balance(address, self.initial_balance)?; - self.executor.set_balance(self.sender, self.initial_balance)?; - self.executor.set_balance(CALLER, self.initial_balance)?; + self.executor.set_balance(address, u256_to_ru256(self.initial_balance))?; + self.executor + .set_balance(h160_to_b160(self.sender), u256_to_ru256(self.initial_balance))?; + self.executor.set_balance(CALLER, u256_to_ru256(self.initial_balance))?; self.executor.deploy_create2_deployer()?; @@ -164,9 +172,18 @@ impl<'a> ContractRunner<'a> { traces.extend(setup_traces.map(|traces| (TraceKind::Setup, traces))); logs.extend(setup_logs); - TestSetup { address, logs, traces, labeled_addresses, reason } + TestSetup { + address: b160_to_h160(address), + logs, + traces, + labeled_addresses: labeled_addresses + .into_iter() + .map(|l| (b160_to_h160(l.0), l.1)) + .collect(), + reason, + } } else { - TestSetup::success(address, logs, traces, Default::default()) + TestSetup::success(b160_to_h160(address), logs, traces, Default::default()) }; Ok(setup) @@ -314,11 +331,11 @@ impl<'a> ContractRunner<'a> { let mut debug_arena = None; let (reverted, reason, gas, stipend, coverage, state_changeset, breakpoints) = match executor.execute_test::<(), _, _>( - self.sender, - address, + h160_to_b160(self.sender), + h160_to_b160(address), func.clone(), (), - 0.into(), + rU256::ZERO, self.errors, ) { Ok(CallResult { @@ -335,14 +352,16 @@ impl<'a> ContractRunner<'a> { .. }) => { traces.extend(execution_trace.map(|traces| (TraceKind::Execution, traces))); - labeled_addresses.extend(new_labels); + labeled_addresses + .extend(new_labels.into_iter().map(|l| (b160_to_h160(l.0), l.1))); logs.extend(execution_logs); debug_arena = debug; (reverted, None, gas, stipend, coverage, state_changeset, breakpoints) } Err(EvmError::Execution(err)) => { traces.extend(err.traces.map(|traces| (TraceKind::Execution, traces))); - labeled_addresses.extend(err.labels); + labeled_addresses + .extend(err.labels.into_iter().map(|l| (b160_to_h160(l.0), l.1))); logs.extend(err.logs); ( err.reverted, @@ -379,7 +398,7 @@ impl<'a> ContractRunner<'a> { }; let success = executor.is_success( - setup.address, + h160_to_b160(setup.address), reverted, state_changeset.expect("we should have a state changeset"), should_fail, @@ -427,11 +446,11 @@ impl<'a> ContractRunner<'a> { // First, run the test normally to see if it needs to be skipped. if let Err(EvmError::SkipError) = self.executor.clone().execute_test::<(), _, _>( - self.sender, - address, + h160_to_b160(self.sender), + h160_to_b160(address), func.clone(), (), - 0.into(), + rU256::ZERO, self.errors, ) { return TestResult { diff --git a/crates/forge/tests/it/config.rs b/crates/forge/tests/it/config.rs index f81472045d69a..6490d7076da0f 100644 --- a/crates/forge/tests/it/config.rs +++ b/crates/forge/tests/it/config.rs @@ -13,6 +13,7 @@ use foundry_config::{ }; use foundry_evm::{ decode::decode_console_logs, executor::inspector::CheatsConfig, revm::primitives::SpecId, + utils::b160_to_h160, }; use std::{ collections::BTreeMap, @@ -143,7 +144,7 @@ pub fn manifest_root() -> PathBuf { /// Builds a base runner pub fn base_runner() -> MultiContractRunnerBuilder { - MultiContractRunnerBuilder::default().sender(EVM_OPTS.sender) + MultiContractRunnerBuilder::default().sender(b160_to_h160(EVM_OPTS.sender)) } /// Builds a non-tracing runner diff --git a/crates/forge/tests/it/test_helpers.rs b/crates/forge/tests/it/test_helpers.rs index b28a3cca0c958..ac66e43a7a067 100644 --- a/crates/forge/tests/it/test_helpers.rs +++ b/crates/forge/tests/it/test_helpers.rs @@ -14,6 +14,7 @@ use foundry_evm::{ DatabaseRef, Executor, ExecutorBuilder, }, fuzz::FuzzedExecutor, + utils::{b160_to_h160, h160_to_b160, u256_to_ru256}, CALLER, }; use std::{path::PathBuf, str::FromStr}; @@ -64,13 +65,13 @@ pub static EVM_OPTS: Lazy = Lazy::new(|| EvmOpts { env: Env { gas_limit: 18446744073709551615, chain_id: None, - tx_origin: Config::DEFAULT_SENDER, + tx_origin: h160_to_b160(Config::DEFAULT_SENDER), block_number: 1, block_timestamp: 1, ..Default::default() }, - sender: Config::DEFAULT_SENDER, - initial_balance: U256::MAX, + sender: h160_to_b160(Config::DEFAULT_SENDER), + initial_balance: u256_to_ru256(U256::MAX), ffi: true, memory_limit: 2u64.pow(24), ..Default::default() @@ -82,7 +83,7 @@ pub fn fuzz_executor(executor: &Executor) -> FuzzedExecutor { FuzzedExecutor::new( executor, proptest::test_runner::TestRunner::new(cfg), - CALLER, + b160_to_h160(CALLER), config::test_opts().fuzz, ) } diff --git a/testdata/cheats/Fork2.t.sol b/testdata/cheats/Fork2.t.sol index 35a1309bbbf95..6d9237e9978e5 100644 --- a/testdata/cheats/Fork2.t.sol +++ b/testdata/cheats/Fork2.t.sol @@ -225,7 +225,7 @@ contract ForkTest is DSTest { string memory path = "fixtures/Rpc/balance_params.json"; string memory file = vm.readFile(path); bytes memory result = vm.rpc("eth_getBalance", file); - assertEq(result, hex"65a221ccb194dc"); + assertEq(result, hex"34f4d7c595f11e"); } }