From 7c63503ef259f292d9f8a1783682609d651e6860 Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Sat, 25 Nov 2023 09:46:33 +0100 Subject: [PATCH 01/13] wip --- Cargo.lock | 653 +++++++++++++++++- Cargo.toml | 23 +- crates/anvil/src/eth/backend/mem/inspector.rs | 4 +- crates/common/src/compile.rs | 17 +- crates/evm/evm/src/inspectors/mod.rs | 2 +- crates/evm/evm/src/inspectors/stack.rs | 16 +- crates/evm/traces/Cargo.toml | 1 + crates/evm/traces/src/lib.rs | 517 +------------- crates/forge/bin/cmd/inspect.rs | 6 +- crates/forge/bin/cmd/selectors.rs | 4 +- 10 files changed, 658 insertions(+), 585 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 293c5b631f16..2adb3e517533 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,15 +82,16 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c18b3ecf1746f0eac255374bdf899dd217dd1b301e4a3f146592234243e1bc66" dependencies = [ - "num_enum", + "num_enum 0.7.1", "serde", "strum", ] [[package]] name = "alloy-dyn-abi" -version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9fe14fb6dded4be3f44d053e59402a405bb231561e36a88bc2283a9829d81fe" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -109,8 +110,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cbbc8fcae58f39dbfbdc94ead48de0779910528889aebc074aed75959bffe7" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -121,7 +123,7 @@ dependencies = [ [[package]] name = "alloy-json-rpc" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#f59761220ee2951c42a44dfd4a7038e4ab17eea4" +source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#ef5a20d940bb35906228d06f7a6dc0ba2418f437" dependencies = [ "alloy-primitives", "serde", @@ -132,7 +134,7 @@ dependencies = [ [[package]] name = "alloy-networks" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#f59761220ee2951c42a44dfd4a7038e4ab17eea4" +source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#ef5a20d940bb35906228d06f7a6dc0ba2418f437" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -141,8 +143,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5def4b5e1bb8fe7ea37eeac1063246d4ef26f56cbdccf864a5a6bdcb80e91f4" dependencies = [ "alloy-rlp", "arbitrary", @@ -166,7 +169,7 @@ dependencies = [ [[package]] name = "alloy-providers" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#f59761220ee2951c42a44dfd4a7038e4ab17eea4" +source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#ef5a20d940bb35906228d06f7a6dc0ba2418f437" dependencies = [ "alloy-networks", "alloy-primitives", @@ -207,7 +210,7 @@ dependencies = [ [[package]] name = "alloy-rpc-client" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#f59761220ee2951c42a44dfd4a7038e4ab17eea4" +source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#ef5a20d940bb35906228d06f7a6dc0ba2418f437" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -224,7 +227,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#f59761220ee2951c42a44dfd4a7038e4ab17eea4" +source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#ef5a20d940bb35906228d06f7a6dc0ba2418f437" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -238,8 +241,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0acd5b8d2699b095a57a0ecea6a6a2045b8e5ed6f2607bfa3382961d2889e82" dependencies = [ "const-hex", "dunce", @@ -255,16 +259,18 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc77699fb68c8a2cf18efb2c51df43e09b42b53886c6eb552951b19c41ebfc84" dependencies = [ "winnow", ] [[package]] name = "alloy-sol-types" -version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d483e9c6db659cdb24fc736684ef68b743705fbdb0677c6404815361871b92" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -275,7 +281,7 @@ dependencies = [ [[package]] name = "alloy-transport" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#f59761220ee2951c42a44dfd4a7038e4ab17eea4" +source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#ef5a20d940bb35906228d06f7a6dc0ba2418f437" dependencies = [ "alloy-json-rpc", "base64 0.21.5", @@ -291,7 +297,7 @@ dependencies = [ [[package]] name = "alloy-transport-http" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#f59761220ee2951c42a44dfd4a7038e4ab17eea4" +source = "git+https://github.com/alloy-rs/alloy/?branch=onbjerg/alloy-temp-provider-trait#ef5a20d940bb35906228d06f7a6dc0ba2418f437" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -702,6 +708,15 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + [[package]] name = "atomic-take" version = "1.1.0" @@ -939,6 +954,144 @@ dependencies = [ "zeroize", ] +[[package]] +name = "boa_ast" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73498e9b2f0aa7db74977afa4d594657611e90587abf0dd564c0b55b4a130163" +dependencies = [ + "bitflags 2.4.1", + "boa_interner", + "boa_macros", + "indexmap 2.1.0", + "num-bigint", + "rustc-hash", +] + +[[package]] +name = "boa_engine" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16377479d5d6d33896e7acdd1cc698d04a8f72004025bbbddf47558cd29146a6" +dependencies = [ + "bitflags 2.4.1", + "boa_ast", + "boa_gc", + "boa_icu_provider", + "boa_interner", + "boa_macros", + "boa_parser", + "boa_profiler", + "chrono", + "dashmap", + "fast-float", + "icu_normalizer", + "indexmap 2.1.0", + "itertools 0.11.0", + "num-bigint", + "num-integer", + "num-traits", + "num_enum 0.6.1", + "once_cell", + "pollster", + "rand 0.8.5", + "regress", + "rustc-hash", + "ryu-js", + "serde", + "serde_json", + "sptr", + "static_assertions", + "tap", + "thin-vec", + "thiserror", +] + +[[package]] +name = "boa_gc" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c97b44beaef9d4452342d117d94607fdfa8d474280f1ba0fd97853834e3a49b2" +dependencies = [ + "boa_macros", + "boa_profiler", + "thin-vec", +] + +[[package]] +name = "boa_icu_provider" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b30e52e34e451dd0bfc2c654a9a43ed34b0073dbd4ae3394b40313edda8627aa" +dependencies = [ + "icu_collections", + "icu_normalizer", + "icu_properties", + "icu_provider", + "icu_provider_adapters", + "icu_provider_blob", + "once_cell", +] + +[[package]] +name = "boa_interner" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3e5afa991908cfbe79bd3109b824e473a1dc5f74f31fab91bb44c9e245daa77" +dependencies = [ + "boa_gc", + "boa_macros", + "hashbrown 0.14.2", + "indexmap 2.1.0", + "once_cell", + "phf 0.11.2", + "rustc-hash", + "static_assertions", +] + +[[package]] +name = "boa_macros" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "005fa0c5bd20805466dda55eb34cd709bb31a2592bb26927b47714eeed6914d8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "synstructure 0.13.0", +] + +[[package]] +name = "boa_parser" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e09afb035377a9044443b598187a7d34cd13164617182a4d7c348522ee3f052" +dependencies = [ + "bitflags 2.4.1", + "boa_ast", + "boa_icu_provider", + "boa_interner", + "boa_macros", + "boa_profiler", + "fast-float", + "icu_locid", + "icu_properties", + "icu_provider", + "icu_provider_macros", + "num-bigint", + "num-traits", + "once_cell", + "regress", + "rustc-hash", + "tinystr", +] + +[[package]] +name = "boa_profiler" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190f92dfe48224adc92881c620f08ccf37ff62b91a094bb357fe53bd5e84647" + [[package]] name = "bs58" version = "0.5.0" @@ -1347,6 +1500,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + [[package]] name = "coins-bip32" version = "0.8.7" @@ -1623,6 +1782,12 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -1957,6 +2122,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -2026,6 +2202,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + [[package]] name = "ena" version = "0.14.2" @@ -2314,7 +2496,7 @@ dependencies = [ "ethabi", "generic-array", "k256", - "num_enum", + "num_enum 0.7.1", "once_cell", "open-fastrlp", "rand 0.8.5", @@ -2499,6 +2681,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fast-float" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" + [[package]] name = "fastrand" version = "2.0.1" @@ -2794,9 +2982,9 @@ dependencies = [ [[package]] name = "foundry-block-explorers" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc59cf4c18884c485b20f376e98946774b76f3b8e2e71e4f35723ffb34b8544" +checksum = "47331ff0955a60df66db753f5dcfe3ca0275abe192e58c9eb6d0d8c1a131e604" dependencies = [ "alloy-chains", "alloy-json-abi", @@ -2933,9 +3121,9 @@ dependencies = [ [[package]] name = "foundry-compilers" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dcfb3af0dd69f2989ab2311f2c97fdd470227d3c9f657be04092572a3a1db60" +checksum = "1eec9fd9df7ad0509ae45e2ea8a595cf13b1f35d69980e985b3be00ffabcc01a" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -2948,6 +3136,7 @@ dependencies = [ "glob", "home", "md-5 0.10.6", + "memmap2 0.9.0", "num_cpus", "once_cell", "path-slash", @@ -3146,6 +3335,7 @@ dependencies = [ "itertools 0.11.0", "once_cell", "ordered-float", + "reth-revm-inspectors", "revm", "serde", "tempfile", @@ -3595,7 +3785,7 @@ dependencies = [ "gix-path", "gix-tempfile", "gix-validate", - "memmap2", + "memmap2 0.5.10", "nom", "thiserror", ] @@ -3755,6 +3945,15 @@ dependencies = [ "ahash 0.7.7", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.6", +] + [[package]] name = "hashbrown" version = "0.14.2" @@ -3991,6 +4190,122 @@ dependencies = [ "cc", ] +[[package]] +name = "icu_collections" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8302d8dfd6044d3ddb3f807a5ef3d7bbca9a574959c6d6e4dc39aa7012d0d5" +dependencies = [ + "displaydoc", + "serde", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3003f85dccfc0e238ff567693248c59153a46f4e6125ba4020b973cef4d1d335" +dependencies = [ + "displaydoc", + "litemap", + "serde", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "652869735c9fb9f5a64ba180ee16f2c848390469c116deef517ecc53f4343598" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_properties", + "icu_provider", + "serde", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_properties" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce0e1aa26851f16c9e04412a5911c86b7f8768dac8f8d4c5f1c568a7e5d7a434" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_provider", + "serde", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_provider" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dc312a7b6148f7dfe098047ae2494d12d4034f48ade58d4f353000db376e305" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "postcard", + "serde", + "stable_deref_trait", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_adapters" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ae1e2bd0c41728b77e7c46e9afdec5e2127d1eedacc684724667d50c126bd3" +dependencies = [ + "icu_locid", + "icu_provider", + "serde", + "tinystr", + "yoke", + "zerovec", +] + +[[package]] +name = "icu_provider_blob" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd364c9a01f791a4bc04a74cf2a1d01d9f6926a40fd5ae1c28004e1e70d8338b" +dependencies = [ + "icu_provider", + "postcard", + "serde", + "writeable", + "yoke", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b728b9421e93eff1d9f8681101b78fa745e0748c95c655c83f337044a7e10" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -4441,6 +4756,12 @@ version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +[[package]] +name = "litemap" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d642685b028806386b2b6e75685faadd3eb65a85fff7df711ce18446a422da" + [[package]] name = "lock_api" version = "0.4.11" @@ -4577,6 +4898,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memmap2" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375" +dependencies = [ + "libc", +] + [[package]] name = "memoffset" version = "0.7.1" @@ -4805,6 +5135,7 @@ dependencies = [ "autocfg", "num-integer", "num-traits", + "serde", ] [[package]] @@ -4869,13 +5200,34 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" +dependencies = [ + "num_enum_derive 0.6.1", +] + [[package]] name = "num_enum" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.7.1", +] + +[[package]] +name = "num_enum_derive" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.39", ] [[package]] @@ -4919,6 +5271,10 @@ name = "once_cell" version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +dependencies = [ + "atomic-polyfill", + "critical-section", +] [[package]] name = "oorandom" @@ -5101,7 +5457,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -5447,12 +5803,29 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "pollster" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" + [[package]] name = "portable-atomic" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "embedded-io", + "serde", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -5885,6 +6258,16 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "regress" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82a9ecfa0cb04d0b04dddb99b8ccf4f66bc8dfd23df694b398570bd8ae3a50fb" +dependencies = [ + "hashbrown 0.13.2", + "memchr", +] + [[package]] name = "reqwest" version = "0.11.22" @@ -5929,10 +6312,45 @@ dependencies = [ "winreg", ] +[[package]] +name = "reth-revm-inspectors" +version = "0.1.0-alpha.11" +source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/tracer-snapshot-type#543e8545a18ad402f2cb98adee144d7dcd8b1e65" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "boa_engine", + "boa_gc", + "reth-rpc-types", + "revm", + "serde", + "serde_json", + "thiserror", + "tokio", +] + +[[package]] +name = "reth-rpc-types" +version = "0.1.0-alpha.11" +source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/tracer-snapshot-type#543e8545a18ad402f2cb98adee144d7dcd8b1e65" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "bytes", + "itertools 0.11.0", + "jsonrpsee-types", + "secp256k1 0.27.0", + "serde", + "serde_json", + "serde_with", + "thiserror", + "url", +] + [[package]] name = "revm" version = "3.5.0" -source = "git+https://github.com/bluealloy/revm?rev=1609e07c68048909ad1682c98cf2b9baa76310b5#1609e07c68048909ad1682c98cf2b9baa76310b5" +source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" dependencies = [ "auto_impl", "revm-interpreter", @@ -5944,7 +6362,7 @@ dependencies = [ [[package]] name = "revm-interpreter" version = "1.3.0" -source = "git+https://github.com/bluealloy/revm?rev=1609e07c68048909ad1682c98cf2b9baa76310b5#1609e07c68048909ad1682c98cf2b9baa76310b5" +source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" dependencies = [ "revm-primitives", "serde", @@ -5953,7 +6371,7 @@ dependencies = [ [[package]] name = "revm-precompile" version = "2.2.0" -source = "git+https://github.com/bluealloy/revm?rev=1609e07c68048909ad1682c98cf2b9baa76310b5#1609e07c68048909ad1682c98cf2b9baa76310b5" +source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -5961,7 +6379,7 @@ dependencies = [ "once_cell", "revm-primitives", "ripemd", - "secp256k1", + "secp256k1 0.28.0", "sha2 0.10.8", "substrate-bn", ] @@ -5969,7 +6387,7 @@ dependencies = [ [[package]] name = "revm-primitives" version = "1.3.0" -source = "git+https://github.com/bluealloy/revm?rev=1609e07c68048909ad1682c98cf2b9baa76310b5#1609e07c68048909ad1682c98cf2b9baa76310b5" +source = "git+https://github.com/bluealloy/revm?branch=reth_freeze#b00ebab8b3477f87e3d876a11b8f18d00a8f4103" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -6076,9 +6494,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "724fd11728a3804e9944b14cab63825024c40bf42f8af87c8b5d97c4bbacf426" +checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" dependencies = [ "alloy-rlp", "arbitrary", @@ -6349,6 +6767,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +[[package]] +name = "ryu-js" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" + [[package]] name = "salsa20" version = "0.10.2" @@ -6466,13 +6890,32 @@ dependencies = [ "zeroize", ] +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "rand 0.8.5", + "secp256k1-sys 0.8.1", +] + [[package]] name = "secp256k1" version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" dependencies = [ - "secp256k1-sys", + "secp256k1-sys 0.9.0", +] + +[[package]] +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", ] [[package]] @@ -6911,6 +7354,18 @@ dependencies = [ "der", ] +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -7053,8 +7508,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.4.2" -source = "git+https://github.com/alloy-rs/core/#0ea90245bdc166e0296fdf70cc4ca329ddbad9e4" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e349ed2ca56eff703d7c3ea013771bcbab9ad2ad39dddf863fc51d820329dc41" dependencies = [ "paste", "proc-macro2", @@ -7080,6 +7536,18 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "unicode-xid", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -7174,6 +7642,12 @@ dependencies = [ "phf_codegen 0.11.2", ] +[[package]] +name = "thin-vec" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8" + [[package]] name = "thiserror" version = "1.0.50" @@ -7253,6 +7727,17 @@ dependencies = [ "crunchy", ] +[[package]] +name = "tinystr" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8faa444297615a4e020acb64146b0603c9c395c03a97c17fd9028816d3b4d63e" +dependencies = [ + "displaydoc", + "serde", + "zerovec", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -7785,6 +8270,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52df8b7fb78e7910d776fccf2e42ceaf3604d55e8e7eb2dbd183cb1441d8a692" + +[[package]] +name = "utf8_iter" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a8922555b9500e3d865caed19330172cd67cbf82203f1a3311d8c305cc9f33" + [[package]] name = "utf8parse" version = "0.2.1" @@ -8223,6 +8720,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad7bb64b8ef9c0aa27b6da38b452b0ee9fd82beaf276a87dd796fb55cbae14e" + [[package]] name = "ws_stream_wasm" version = "0.7.4" @@ -8269,6 +8778,30 @@ version = "1.0.0-rc.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1367295b8f788d371ce2dbc842c7b709c73ee1364d30351dd300ec2203b12377" +[[package]] +name = "yoke" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e71b2e4f287f467794c671e2b8f8a5f3716b3c829079a1c44740148eff07e4" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "synstructure 0.13.0", +] + [[package]] name = "zerocopy" version = "0.7.26" @@ -8289,6 +8822,27 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "zerofrom" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", + "synstructure 0.13.0", +] + [[package]] name = "zeroize" version = "1.7.0" @@ -8309,6 +8863,29 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "zerovec" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "591691014119b87047ead4dcf3e6adfbf73cb7c38ab6980d4f18a32138f35d46" +dependencies = [ + "serde", + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a4a1638a1934450809c2266a70362bfc96cd90550c073f5b8a55014d1010157" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "zip" version = "0.6.6" diff --git a/Cargo.toml b/Cargo.toml index 4f9cf429050d..b9a7b4c79839 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,9 +132,9 @@ foundry-test-utils = { path = "crates/test-utils" } foundry-utils = { path = "crates/utils" } # block explorer & verification bindings -foundry-block-explorers = { version = "0.1", default-features = false } +foundry-block-explorers = { version = "0.1.1", default-features = false } # solc & compilation utilities -foundry-compilers = { version = "0.1", default-features = false } +foundry-compilers = { version = "0.1.1", default-features = false } ## revm # no default features to avoid c-kzg @@ -152,11 +152,11 @@ ethers-middleware = { version = "2.0", default-features = false } ethers-solc = { version = "2.0", default-features = false } ## alloy -alloy-primitives = "0.4.1" -alloy-dyn-abi = "0.4.1" -alloy-json-abi = "0.4.1" -alloy-sol-types = "0.4.1" -syn-solidity = "0.4.1" +alloy-primitives = "0.5.0" +alloy-dyn-abi = "0.5.0" +alloy-json-abi = "0.5.0" +alloy-sol-types = "0.5.0" +syn-solidity = "0.5.0" alloy-providers = "0.1.0" alloy-transport = "0.1.0" alloy-transport-http = "0.1.0" @@ -216,10 +216,5 @@ alloy-transport = { git = "https://github.com/alloy-rs/alloy/", branch = "onbjer alloy-transport-http = { git = "https://github.com/alloy-rs/alloy/", branch = "onbjerg/alloy-temp-provider-trait" } alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy/", branch = "onbjerg/alloy-temp-provider-trait" } -alloy-dyn-abi = { git = "https://github.com/alloy-rs/core/" } -alloy-primitives = { git = "https://github.com/alloy-rs/core/" } -alloy-json-abi = { git = "https://github.com/alloy-rs/core/" } -alloy-sol-types = { git = "https://github.com/alloy-rs/core/" } - -revm = { git = "https://github.com/bluealloy/revm", rev = "1609e07c68048909ad1682c98cf2b9baa76310b5" } -revm-primitives = { git = "https://github.com/bluealloy/revm", rev = "1609e07c68048909ad1682c98cf2b9baa76310b5" } \ No newline at end of file +revm = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze" } +revm-primitives = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze" } \ No newline at end of file diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index 295558408ba3..df3e4f2f9cf6 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -5,7 +5,7 @@ use ethers::types::Log; use foundry_evm::{ call_inspectors, decode::decode_console_logs, - inspectors::{LogCollector, Tracer}, + inspectors::{LogCollector, TracingInspector}, revm, revm::{ interpreter::{CallInputs, CreateInputs, Gas, InstructionResult, Interpreter}, @@ -17,7 +17,7 @@ use foundry_evm::{ /// The [`revm::Inspector`] used when transacting in the evm #[derive(Debug, Clone, Default)] pub struct Inspector { - pub tracer: Option, + pub tracer: Option, /// collects all `console.sol` logs pub log_collector: LogCollector, } diff --git a/crates/common/src/compile.rs b/crates/common/src/compile.rs index 4362662e9a8f..749ef15f2388 100644 --- a/crates/common/src/compile.rs +++ b/crates/common/src/compile.rs @@ -148,15 +148,14 @@ impl ProjectCompiler { for (name, artifact) in artifacts { let size = deployed_contract_size(artifact).unwrap_or_default(); - let dev_functions = artifact - .abi - .as_ref() - .map(|abi| abi.abi.functions()) - .into_iter() - .flatten() - .filter(|func| { - func.name.is_test() || func.name.eq("IS_TEST") || func.name.eq("IS_SCRIPT") - }); + let dev_functions = + artifact.abi.as_ref().map(|abi| abi.functions()).into_iter().flatten().filter( + |func| { + func.name.is_test() || + func.name.eq("IS_TEST") || + func.name.eq("IS_SCRIPT") + }, + ); let is_dev_contract = dev_functions.count() > 0; size_report.contracts.insert(name, ContractInfo { size, is_dev_contract }); diff --git a/crates/evm/evm/src/inspectors/mod.rs b/crates/evm/evm/src/inspectors/mod.rs index b781ce96c8dd..20dd340d3cda 100644 --- a/crates/evm/evm/src/inspectors/mod.rs +++ b/crates/evm/evm/src/inspectors/mod.rs @@ -3,7 +3,7 @@ pub use foundry_cheatcodes::{self as cheatcodes, Cheatcodes, CheatsConfig}; pub use foundry_evm_coverage::CoverageCollector; pub use foundry_evm_fuzz::Fuzzer; -pub use foundry_evm_traces::Tracer; +pub use foundry_evm_traces::{StackSnapshotType, TracingInspector, TracingInspectorConfig}; mod access_list; pub use access_list::AccessListTracer; diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index 34795bca2de2..d95d24d68b3c 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -1,6 +1,6 @@ use super::{ Cheatcodes, CheatsConfig, ChiselState, CoverageCollector, Debugger, Fuzzer, LogCollector, - TracePrinter, Tracer, + StackSnapshotType, TracePrinter, TracingInspector, TracingInspectorConfig, }; use alloy_primitives::{Address, Bytes, B256, U256}; use ethers_core::types::Log; @@ -208,7 +208,7 @@ pub struct InspectorStack { pub fuzzer: Option, pub log_collector: Option, pub printer: Option, - pub tracer: Option, + pub tracer: Option, } impl InspectorStack { @@ -290,7 +290,17 @@ impl InspectorStack { /// Set whether to enable the tracer. #[inline] pub fn tracing(&mut self, yes: bool) { - self.tracer = yes.then(Default::default); + self.tracer = yes.then(|| { + TracingInspector::new(TracingInspectorConfig { + record_steps: false, + record_memory_snapshots: false, + record_stack_snapshots: StackSnapshotType::None, + record_state_diff: false, + exclude_precompile_calls: false, + record_call_return_data: true, + record_logs: true, + }) + }); } /// Collects all the data gathered during inspection into a single struct. diff --git a/crates/evm/traces/Cargo.toml b/crates/evm/traces/Cargo.toml index 7edaedd94e0f..a9c713964fcd 100644 --- a/crates/evm/traces/Cargo.toml +++ b/crates/evm/traces/Cargo.toml @@ -23,6 +23,7 @@ alloy-json-abi.workspace = true alloy-primitives = { workspace = true, features = ["serde", "getrandom", "arbitrary", "rlp"] } alloy-sol-types.workspace = true revm.workspace = true +reth-revm-inspectors = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/tracer-snapshot-type" } ethers-core.workspace = true diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 98b05188d8ff..f182ee7a213b 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -31,530 +31,21 @@ use identifier::LocalTraceIdentifier; mod decoder; pub use decoder::{CallTraceDecoder, CallTraceDecoderBuilder}; -mod inspector; -pub use inspector::Tracer; - -mod node; -pub use node::CallTraceNode; +pub use reth_revm_inspectors::tracing::{ + types::{CallTrace, CallTraceNode}, + CallTraceArena, StackSnapshotType, TracingInspector, TracingInspectorConfig, +}; pub mod utils; pub type Traces = Vec<(TraceKind, CallTraceArena)>; -/// An arena of [CallTraceNode]s -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct CallTraceArena { - /// The arena of nodes - pub arena: Vec, -} - -impl Default for CallTraceArena { - fn default() -> Self { - CallTraceArena { arena: vec![Default::default()] } - } -} - -impl CallTraceArena { - /// Pushes a new trace into the arena, returning the trace ID - pub fn push_trace(&mut self, entry: usize, new_trace: CallTrace) -> usize { - match new_trace.depth { - // The entry node, just update it - 0 => { - self.arena[0].trace = new_trace; - 0 - } - // We found the parent node, add the new trace as a child - _ if self.arena[entry].trace.depth == new_trace.depth - 1 => { - let id = self.arena.len(); - - let trace_location = self.arena[entry].children.len(); - self.arena[entry].ordering.push(LogCallOrder::Call(trace_location)); - let node = CallTraceNode { - parent: Some(entry), - trace: new_trace, - idx: id, - ..Default::default() - }; - self.arena.push(node); - self.arena[entry].children.push(id); - - id - } - // We haven't found the parent node, go deeper - _ => self.push_trace( - *self.arena[entry].children.last().expect("Disconnected trace"), - new_trace, - ), - } - } - - pub fn addresses(&self) -> HashSet<(&Address, Option<&[u8]>)> { - self.arena - .iter() - .map(|node| { - if node.trace.created() { - if let TraceRetData::Raw(bytes) = &node.trace.output { - return (&node.trace.address, Some(bytes.as_ref())) - } - } - - (&node.trace.address, None) - }) - .collect() - } - - // Recursively fill in the geth trace by going through the traces - fn add_to_geth_trace( - &self, - storage: &mut HashMap>, - trace_node: &CallTraceNode, - struct_logs: &mut Vec, - opts: &GethDebugTracingOptions, - ) { - let mut child_id = 0; - // Iterate over the steps inside the given trace - for step in trace_node.trace.steps.iter() { - let mut log: StructLog = step.into(); - - // Fill in memory and storage depending on the options - if !opts.disable_storage.unwrap_or_default() { - let contract_storage = storage.entry(step.contract).or_default(); - if let Some((key, value)) = step.state_diff { - contract_storage.insert(B256::from(key), B256::from(value)); - log.storage = Some( - contract_storage - .iter_mut() - .map(|t| (t.0.to_ethers(), t.1.to_ethers())) - .collect(), - ); - } - } - if opts.disable_stack.unwrap_or_default() { - log.stack = None; - } - if !opts.enable_memory.unwrap_or_default() { - log.memory = None; - } - - // Add step to geth trace - struct_logs.push(log); - - // Descend into a child trace if the step was a call - if let Instruction::OpCode( - opcode::CREATE | - opcode::CREATE2 | - opcode::DELEGATECALL | - opcode::CALL | - opcode::STATICCALL | - opcode::CALLCODE, - ) = step.op - { - self.add_to_geth_trace( - storage, - &self.arena[trace_node.children[child_id]], - struct_logs, - opts, - ); - child_id += 1; - } - } - } - - /// Generate a geth-style trace e.g. for debug_traceTransaction - pub fn geth_trace( - &self, - receipt_gas_used: U256, - opts: GethDebugTracingOptions, - ) -> DefaultFrame { - if self.arena.is_empty() { - return Default::default() - } - - let mut storage = HashMap::new(); - // Fetch top-level trace - let main_trace_node = &self.arena[0]; - let main_trace = &main_trace_node.trace; - // Start geth trace - let mut acc = DefaultFrame { - // If the top-level trace succeeded, then it was a success - failed: !main_trace.success, - gas: receipt_gas_used.to_ethers(), - return_value: main_trace.output.to_bytes().0.into(), - ..Default::default() - }; - - self.add_to_geth_trace(&mut storage, main_trace_node, &mut acc.struct_logs, &opts); - - acc - } -} - const PIPE: &str = " │ "; const EDGE: &str = " └─ "; const BRANCH: &str = " ├─ "; const CALL: &str = "→ "; const RETURN: &str = "← "; -impl fmt::Display for CallTraceArena { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fn inner( - arena: &CallTraceArena, - f: &mut fmt::Formatter<'_>, - idx: usize, - left: &str, - child: &str, - ) -> fmt::Result { - let node = &arena.arena[idx]; - - // Display trace header - writeln!(f, "{left}{}", node.trace)?; - - // Display logs and subcalls - let left_prefix = format!("{child}{BRANCH}"); - let right_prefix = format!("{child}{PIPE}"); - for child in &node.ordering { - match child { - LogCallOrder::Log(index) => { - let log = node.logs[*index].to_string(); - // Prepend our tree structure symbols to each line of the displayed log - log.lines().enumerate().try_for_each(|(i, line)| { - writeln!( - f, - "{}{}", - if i == 0 { &left_prefix } else { &right_prefix }, - line - ) - })?; - } - LogCallOrder::Call(index) => { - inner(arena, f, node.children[*index], &left_prefix, &right_prefix)?; - } - } - } - - // Display trace return data - let color = trace_color(&node.trace); - write!(f, "{child}{EDGE}{}", color.paint(RETURN))?; - if node.trace.created() { - match &node.trace.output { - TraceRetData::Raw(bytes) => { - writeln!(f, "{} bytes of code", bytes.len())?; - } - TraceRetData::Decoded(val) => { - writeln!(f, "{val}")?; - } - } - } else { - writeln!(f, "{}", node.trace.output)?; - } - - Ok(()) - } - - inner(self, f, 0, " ", " ") - } -} - -/// A raw or decoded log. -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum TraceLog { - /// A raw log - Raw(RawLog), - /// A decoded log. - /// - /// The first member of the tuple is the event name, and the second is a vector of decoded - /// parameters. - Decoded(String, Vec<(String, String)>), -} - -impl fmt::Display for TraceLog { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - TraceLog::Raw(log) => { - for (i, topic) in log.topics().iter().enumerate() { - writeln!( - f, - "{:>13}: {}", - if i == 0 { "emit topic 0".to_string() } else { format!("topic {i}") }, - Paint::cyan(format!("{topic:?}")) - )?; - } - - write!(f, " data: {}", Paint::cyan(hex::encode_prefixed(&log.data))) - } - TraceLog::Decoded(name, params) => { - let params = params - .iter() - .map(|(name, value)| format!("{name}: {value}")) - .collect::>() - .join(", "); - - write!(f, "emit {}({params})", Paint::cyan(name.clone())) - } - } - } -} - -/// Ordering enum for calls and logs -/// -/// i.e. if Call 0 occurs before Log 0, it will be pushed into the `CallTraceNode`'s ordering before -/// the log. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum LogCallOrder { - Log(usize), - Call(usize), -} - -/// Raw or decoded calldata. -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub enum TraceCallData { - /// Raw calldata bytes. - Raw(Bytes), - /// Decoded calldata. - Decoded { - /// The function signature. - signature: String, - /// The function arguments. - args: Vec, - }, -} - -impl Default for TraceCallData { - fn default() -> Self { - Self::Raw(Bytes::new()) - } -} - -impl TraceCallData { - pub fn as_bytes(&self) -> &[u8] { - match self { - TraceCallData::Raw(raw) => raw, - TraceCallData::Decoded { .. } => &[], - } - } -} - -/// Raw or decoded return data. -#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)] -pub enum TraceRetData { - /// Raw return data. - Raw(Bytes), - /// Decoded return data. - Decoded(String), -} - -impl Default for TraceRetData { - fn default() -> Self { - Self::Raw(Bytes::new()) - } -} - -impl TraceRetData { - /// Returns the data as [`Bytes`] - pub fn to_bytes(&self) -> Bytes { - match self { - TraceRetData::Raw(raw) => raw.clone(), - TraceRetData::Decoded(val) => val.as_bytes().to_vec().into(), - } - } - - pub fn to_raw(&self) -> Vec { - self.to_bytes().to_vec() - } -} - -impl fmt::Display for TraceRetData { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self { - TraceRetData::Raw(bytes) => { - if bytes.is_empty() { - write!(f, "()") - } else { - bytes.fmt(f) - } - } - TraceRetData::Decoded(decoded) => f.write_str(decoded), - } - } -} - -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct CallTraceStep { - // Fields filled in `step` - /// Call depth - pub depth: u64, - /// Program counter before step execution - pub pc: usize, - /// Opcode to be executed - pub op: Instruction, - /// Current contract address - pub contract: Address, - /// Stack before step execution - pub stack: Stack, - /// Memory before step execution - pub memory: SharedMemory, - /// Remaining gas before step execution - pub gas: u64, - /// Gas refund counter before step execution - pub gas_refund_counter: u64, - - // Fields filled in `step_end` - /// Gas cost of step execution - pub gas_cost: u64, - /// Change of the contract state after step execution (effect of the SLOAD/SSTORE instructions) - pub state_diff: Option<(U256, U256)>, - /// Error (if any) after step execution - pub error: Option, -} - -impl From<&CallTraceStep> for StructLog { - fn from(step: &CallTraceStep) -> Self { - StructLog { - depth: step.depth, - error: step.error.clone(), - gas: step.gas, - gas_cost: step.gas_cost, - memory: Some(convert_memory(step.memory.context_memory())), - op: step.op.to_string(), - pc: step.pc as u64, - refund_counter: if step.gas_refund_counter > 0 { - Some(step.gas_refund_counter) - } else { - None - }, - stack: Some(step.stack.data().iter().copied().map(|v| v.to_ethers()).collect_vec()), - // Filled in `CallTraceArena::geth_trace` as a result of compounding all slot changes - storage: None, - return_data: None, - mem_size: None, - } - } -} - -/// A trace of a call. -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] -pub struct CallTrace { - /// The depth of the call - pub depth: usize, - /// Whether the call was successful - pub success: bool, - /// The name of the contract, if any. - /// - /// The format is `":"` for easy lookup in local contracts. - /// - /// This member is not used by the core call tracing functionality (decoding/displaying). The - /// intended use case is for other components that may want to process traces by specific - /// contracts (e.g. gas reports). - pub contract: Option, - /// The label for the destination address, if any - pub label: Option, - /// caller of this call - pub caller: Address, - /// The destination address of the call or the address from the created contract - pub address: Address, - /// The kind of call this is - pub kind: CallKind, - /// The value transferred in the call - pub value: U256, - /// The calldata for the call, or the init code for contract creations - pub data: TraceCallData, - /// The return data of the call if this was not a contract creation, otherwise it is the - /// runtime bytecode of the created contract - pub output: TraceRetData, - /// The gas cost of the call - pub gas_cost: u64, - /// The status of the trace's call - pub status: InstructionResult, - /// call context of the runtime - pub call_context: Option, - /// Opcode-level execution steps - pub steps: Vec, -} - -impl CallTrace { - /// Whether this is a contract creation or not - pub fn created(&self) -> bool { - matches!(self.kind, CallKind::Create | CallKind::Create2) - } -} - -impl Default for CallTrace { - fn default() -> Self { - Self { - depth: Default::default(), - success: Default::default(), - contract: Default::default(), - label: Default::default(), - caller: Default::default(), - address: Default::default(), - kind: Default::default(), - value: Default::default(), - data: Default::default(), - output: Default::default(), - gas_cost: Default::default(), - status: InstructionResult::Continue, - call_context: Default::default(), - steps: Default::default(), - } - } -} - -impl fmt::Display for CallTrace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "[{}] ", self.gas_cost)?; - let address = self.address.to_checksum(None); - if self.created() { - write!( - f, - "{}{} {}@{}", - Paint::yellow(CALL), - Paint::yellow("new"), - self.label.as_deref().unwrap_or(""), - address - ) - } else { - let (func_name, inputs) = match &self.data { - TraceCallData::Raw(bytes) => { - debug!(target: "evm::traces", trace=?self, "unhandled raw calldata"); - if bytes.len() < 4 { - ("fallback".into(), hex::encode(bytes)) - } else { - let (selector, data) = bytes.split_at(4); - (hex::encode(selector), hex::encode(data)) - } - } - TraceCallData::Decoded { signature, args } => { - let name = signature.split('(').next().unwrap(); - (name.to_string(), args.join(", ")) - } - }; - - let action = match self.kind { - // do not show anything for CALLs - CallKind::Call => "", - CallKind::StaticCall => " [staticcall]", - CallKind::CallCode => " [callcode]", - CallKind::DelegateCall => " [delegatecall]", - CallKind::Create | CallKind::Create2 => unreachable!(), - }; - - let color = trace_color(self); - write!( - f, - "{addr}::{func_name}{opt_value}({inputs}){action}", - addr = color.paint(self.label.as_deref().unwrap_or(&address)), - func_name = color.paint(func_name), - opt_value = if self.value == U256::ZERO { - String::new() - } else { - format!("{{value: {}}}", self.value) - }, - action = Paint::yellow(action), - ) - } - } -} - /// Specifies the kind of trace. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum TraceKind { diff --git a/crates/forge/bin/cmd/inspect.rs b/crates/forge/bin/cmd/inspect.rs index e7fc089ec55b..7e78f7ae7578 100644 --- a/crates/forge/bin/cmd/inspect.rs +++ b/crates/forge/bin/cmd/inspect.rs @@ -89,7 +89,7 @@ impl InspectArgs { .abi .as_ref() .ok_or_else(|| eyre::eyre!("Failed to fetch lossless ABI"))?; - print_abi(&abi.abi, pretty)?; + print_abi(abi, pretty)?; } ContractArtifactField::Bytecode => { let tval: Value = to_value(&artifact.bytecode)?; @@ -165,7 +165,7 @@ impl InspectArgs { ContractArtifactField::Errors => { let mut out = serde_json::Map::new(); if let Some(abi) = &artifact.abi { - let abi = &abi.abi; + let abi = &abi; // Print the signature of all errors for er in abi.errors.iter().flat_map(|(_, errors)| errors) { let types = er.inputs.iter().map(|p| p.ty.clone()).collect::>(); @@ -182,7 +182,7 @@ impl InspectArgs { ContractArtifactField::Events => { let mut out = serde_json::Map::new(); if let Some(abi) = &artifact.abi { - let abi = &abi.abi; + let abi = &abi; // print the signature of all events including anonymous for ev in abi.events.iter().flat_map(|(_, events)| events) { let types = ev.inputs.iter().map(|p| p.ty.clone()).collect::>(); diff --git a/crates/forge/bin/cmd/selectors.rs b/crates/forge/bin/cmd/selectors.rs index 05b87b7efe71..4b2d045c9ddf 100644 --- a/crates/forge/bin/cmd/selectors.rs +++ b/crates/forge/bin/cmd/selectors.rs @@ -106,7 +106,7 @@ impl SelectorsSubcommands { let mut artifacts = artifacts.into_iter().peekable(); while let Some((contract, artifact)) = artifacts.next() { - let abi = artifact.abi.ok_or_else(|| eyre::eyre!("Unable to fetch abi"))?.abi; + let abi = artifact.abi.ok_or_else(|| eyre::eyre!("Unable to fetch abi"))?; if abi.functions.is_empty() && abi.events.is_empty() && abi.errors.is_empty() { continue } @@ -234,7 +234,7 @@ impl SelectorsSubcommands { let mut artifacts = artifacts.into_iter().peekable(); while let Some((contract, artifact)) = artifacts.next() { - let abi = artifact.abi.ok_or_else(|| eyre::eyre!("Unable to fetch abi"))?.abi; + let abi = artifact.abi.ok_or_else(|| eyre::eyre!("Unable to fetch abi"))?; if abi.functions.is_empty() && abi.events.is_empty() && abi.errors.is_empty() { continue } From 2feac7b5304e40130baaa79a5614615b51163f0e Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 4 Dec 2023 10:50:36 +0100 Subject: [PATCH 02/13] wip not working still -.- - gas reports - `forge script` cannot set `gas_used` for root trace since that requires mut access to the arena - event decoding not impl possibly broken - anvil traces (not tested) - test traces (not tested) - debugging (not tested) but hey, at least it compiles... --- Cargo.lock | 10 +- crates/anvil/Cargo.toml | 2 + crates/anvil/core/Cargo.toml | 1 + crates/anvil/core/src/eth/mod.rs | 226 ++++++++++-------- crates/anvil/core/src/eth/transaction/mod.rs | 43 +--- crates/anvil/src/eth/api.rs | 75 +++--- crates/anvil/src/eth/backend/executor.rs | 10 +- crates/anvil/src/eth/backend/mem/inspector.rs | 10 +- crates/anvil/src/eth/backend/mem/mod.rs | 66 ++--- crates/anvil/src/eth/backend/mem/storage.rs | 65 +++-- crates/anvil/src/eth/otterscan/api.rs | 40 ++-- crates/anvil/src/eth/otterscan/types.rs | 33 +-- crates/chisel/src/dispatcher.rs | 7 +- crates/cli/src/utils/cmd.rs | 13 +- crates/evm/evm/src/executors/mod.rs | 4 +- crates/evm/evm/src/inspectors/stack.rs | 2 +- crates/evm/fuzz/src/lib.rs | 1 + crates/evm/traces/Cargo.toml | 2 +- crates/evm/traces/src/decoder/mod.rs | 134 ++++++----- crates/evm/traces/src/decoder/precompiles.rs | 18 +- crates/evm/traces/src/lib.rs | 179 +++++++++++++- crates/forge/bin/cmd/script/executor.rs | 13 +- crates/forge/bin/cmd/script/mod.rs | 41 ++-- crates/forge/bin/cmd/script/runner.rs | 6 +- crates/forge/bin/cmd/script/transaction.rs | 5 +- crates/forge/bin/cmd/test/mod.rs | 34 +-- crates/forge/src/gas_report.rs | 5 +- crates/forge/src/result.rs | 1 + 28 files changed, 590 insertions(+), 456 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2adb3e517533..958cd98e00c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,6 +428,7 @@ dependencies = [ "parking_lot", "pretty_assertions", "rand 0.8.5", + "reth-rpc-types", "serde", "serde_json", "serde_repr", @@ -459,6 +460,7 @@ dependencies = [ "keccak-hasher", "open-fastrlp", "reference-trie", + "reth-rpc-types", "revm", "serde", "serde_json", @@ -6314,8 +6316,8 @@ dependencies = [ [[package]] name = "reth-revm-inspectors" -version = "0.1.0-alpha.11" -source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/tracer-snapshot-type#543e8545a18ad402f2cb98adee144d7dcd8b1e65" +version = "0.1.0-alpha.12" +source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/trace-builder#64b2ce23cad2d3b68700ad5bc007b83e6a61e3ac" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -6331,8 +6333,8 @@ dependencies = [ [[package]] name = "reth-rpc-types" -version = "0.1.0-alpha.11" -source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/tracer-snapshot-type#543e8545a18ad402f2cb98adee144d7dcd8b1e65" +version = "0.1.0-alpha.12" +source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/trace-builder#64b2ce23cad2d3b68700ad5bc007b83e6a61e3ac" dependencies = [ "alloy-primitives", "alloy-rlp", diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 537484387151..8156bf3b721b 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -38,6 +38,8 @@ alloy-primitives = { workspace = true, features = ["serde"] } alloy-rpc-types.workspace = true alloy-providers.workspace = true alloy-transport.workspace = true +reth-rpc-types = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/trace-builder" } + # axum related axum.workspace = true diff --git a/crates/anvil/core/Cargo.toml b/crates/anvil/core/Cargo.toml index 6fc6ca936a72..7fbd2c394459 100644 --- a/crates/anvil/core/Cargo.toml +++ b/crates/anvil/core/Cargo.toml @@ -23,6 +23,7 @@ serde = { workspace = true, optional = true } serde_json.workspace = true bytes = { version = "1.4" } open-fastrlp = { version = "0.1.4", optional = true } +reth-rpc-types = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/trace-builder" } # trie hash-db = { version = "0.15", default-features = false } diff --git a/crates/anvil/core/src/eth/mod.rs b/crates/anvil/core/src/eth/mod.rs index bc46f203cf03..0ce36e73aa05 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -8,16 +8,17 @@ use alloy_rpc_types::{ state::StateOverride, BlockId, BlockNumberOrTag as BlockNumber, CallRequest, Filter, TransactionRequest, }; -use ethers_core::types::{transaction::eip712::TypedData, GethDebugTracingOptions}; +use ethers_core::types::transaction::eip712::TypedData; +use reth_rpc_types::trace::geth::GethDefaultTracingOptions; pub mod block; pub mod proof; pub mod receipt; +pub mod state; pub mod subscription; pub mod transaction; pub mod trie; pub mod utils; -pub mod state; #[cfg(feature = "serde")] pub mod serde_helpers; @@ -26,7 +27,9 @@ pub mod serde_helpers; use self::serde_helpers::*; #[cfg(feature = "serde")] -use foundry_common::serde_helpers::{deserialize_number, deserialize_number_opt, deserialize_number_seq}; +use foundry_common::serde_helpers::{ + deserialize_number, deserialize_number_opt, deserialize_number_seq, +}; /// Wrapper type that ensures the type is named `params` #[derive(Debug, Clone, PartialEq, Eq)] @@ -88,9 +91,13 @@ pub enum EthRequest { #[cfg_attr(feature = "serde", serde(rename = "eth_getBlockByNumber"))] EthGetBlockByNumber( - #[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number"))] - BlockNumber, - bool), + #[cfg_attr( + feature = "serde", + serde(deserialize_with = "lenient_block_number::lenient_block_number") + )] + BlockNumber, + bool, + ), #[cfg_attr(feature = "serde", serde(rename = "eth_getTransactionCount"))] EthGetTransactionCount(Address, Option), @@ -191,9 +198,12 @@ pub enum EthRequest { #[cfg_attr(feature = "serde", serde(rename = "eth_getUncleByBlockNumberAndIndex"))] EthGetUncleByBlockNumberAndIndex( - #[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number"))] - BlockNumber, - Index + #[cfg_attr( + feature = "serde", + serde(deserialize_with = "lenient_block_number::lenient_block_number") + )] + BlockNumber, + Index, ), #[cfg_attr(feature = "serde", serde(rename = "eth_getLogs", with = "sequence"))] @@ -251,7 +261,7 @@ pub enum EthRequest { #[cfg_attr(feature = "serde", serde(rename = "debug_traceTransaction"))] DebugTraceTransaction( B256, - #[cfg_attr(feature = "serde", serde(default))] GethDebugTracingOptions, + #[cfg_attr(feature = "serde", serde(default))] GethDefaultTracingOptions, ), /// geth's `debug_traceCall` endpoint @@ -259,7 +269,7 @@ pub enum EthRequest { DebugTraceCall( CallRequest, #[cfg_attr(feature = "serde", serde(default))] Option, - #[cfg_attr(feature = "serde", serde(default))] GethDebugTracingOptions, + #[cfg_attr(feature = "serde", serde(default))] GethDefaultTracingOptions, ), /// Trace transaction endpoint for parity's `trace_transaction` @@ -269,7 +279,10 @@ pub enum EthRequest { /// Trace transaction endpoint for parity's `trace_block` #[cfg_attr( feature = "serde", - serde(rename = "trace_block", deserialize_with = "lenient_block_number::lenient_block_number_seq") + serde( + rename = "trace_block", + deserialize_with = "lenient_block_number::lenient_block_number_seq" + ) )] TraceBlock(BlockNumber), @@ -606,8 +619,11 @@ pub enum EthRequest { /// Related upstream issue: https://github.com/otterscan/otterscan/issues/1081 #[cfg_attr(feature = "serde", serde(rename = "erigon_getHeaderByNumber"))] ErigonGetHeaderByNumber( - #[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number_seq"))] - BlockNumber + #[cfg_attr( + feature = "serde", + serde(deserialize_with = "lenient_block_number::lenient_block_number_seq") + )] + BlockNumber, ), /// Otterscan's `ots_getApiLevel` endpoint @@ -625,9 +641,12 @@ pub enum EthRequest { /// Check if an ETH address contains code at a certain block number. #[cfg_attr(feature = "serde", serde(rename = "ots_hasCode"))] OtsHasCode( - Address, - #[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number", default))] - BlockNumber + Address, + #[cfg_attr( + feature = "serde", + serde(deserialize_with = "lenient_block_number::lenient_block_number", default) + )] + BlockNumber, ), /// Otterscan's `ots_traceTransaction` endpoint @@ -646,8 +665,11 @@ pub enum EthRequest { /// logBloom #[cfg_attr(feature = "serde", serde(rename = "ots_getBlockDetails"))] OtsGetBlockDetails( - #[cfg_attr(feature = "serde", serde(deserialize_with = "lenient_block_number::lenient_block_number", default))] - BlockNumber + #[cfg_attr( + feature = "serde", + serde(deserialize_with = "lenient_block_number::lenient_block_number", default) + )] + BlockNumber, ), /// Otterscan's `ots_getBlockDetails` endpoint @@ -791,16 +813,18 @@ mod tests { #[test] fn test_custom_impersonate_account() { let s = r#"{"method": "anvil_impersonateAccount", "params": -["0xd84de507f3fada7df80908082d3239466db55a71"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0xd84de507f3fada7df80908082d3239466db55a71"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_custom_stop_impersonate_account() { let s = r#"{"method": "anvil_stopImpersonatingAccount", "params": -["0x364d6D0333432C3Ac016Ca832fb8594A8cE43Ca6"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0x364d6D0333432C3Ac016Ca832fb8594A8cE43Ca6"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_custom_auto_impersonate_account() { @@ -828,11 +852,11 @@ serde_json::from_value::(value).unwrap(); } } _ => unreachable!(), } - let s = - r#"{"method": "anvil_mine", "params": -["0xd84de507f3fada7df80908082d3239466db55a71"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let req = -serde_json::from_value::(value).unwrap(); match req { + let s = r#"{"method": "anvil_mine", "params": +["0xd84de507f3fada7df80908082d3239466db55a71"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let req = serde_json::from_value::(value).unwrap(); + match req { EthRequest::Mine(num, time) => { assert!(num.is_some()); assert!(time.is_none()); @@ -874,9 +898,10 @@ serde_json::from_value::(value).unwrap(); match req { #[test] fn test_custom_drop_tx() { let s = r#"{"method": "anvil_dropTransaction", "params": -["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_custom_reset() { @@ -1019,67 +1044,73 @@ serde_json::from_value::(value).unwrap(); } #[test] fn test_custom_set_balance() { let s = r#"{"method": "anvil_setBalance", "params": -["0xd84de507f3fada7df80908082d3239466db55a71", "0x0"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); +["0xd84de507f3fada7df80908082d3239466db55a71", "0x0"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"method": "anvil_setBalance", "params": -["0xd84de507f3fada7df80908082d3239466db55a71", 1337]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0xd84de507f3fada7df80908082d3239466db55a71", 1337]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_custom_set_code() { let s = r#"{"method": "anvil_setCode", "params": -["0xd84de507f3fada7df80908082d3239466db55a71", "0x0123456789abcdef"]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); +["0xd84de507f3fada7df80908082d3239466db55a71", "0x0123456789abcdef"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"method": "anvil_setCode", "params": -["0xd84de507f3fada7df80908082d3239466db55a71", "0x"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); +["0xd84de507f3fada7df80908082d3239466db55a71", "0x"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"method": "anvil_setCode", "params": -["0xd84de507f3fada7df80908082d3239466db55a71", ""]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0xd84de507f3fada7df80908082d3239466db55a71", ""]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_custom_set_nonce() { let s = r#"{"method": "anvil_setNonce", "params": -["0xd84de507f3fada7df80908082d3239466db55a71", "0x0"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); let s = r#"{"method": +["0xd84de507f3fada7df80908082d3239466db55a71", "0x0"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + let s = r#"{"method": "hardhat_setNonce", "params": ["0xd84de507f3fada7df80908082d3239466db55a71", "0x0"]}"#; let value: serde_json::Value = serde_json::from_str(s).unwrap(); let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"method": "evm_setAccountNonce", "params": -["0xd84de507f3fada7df80908082d3239466db55a71", "0x0"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0xd84de507f3fada7df80908082d3239466db55a71", "0x0"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_serde_custom_set_storage_at() { let s = r#"{"method": "anvil_setStorageAt", "params": ["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", -"0x0000000000000000000000000000000000000000000000000000000000003039"]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); +"0x0000000000000000000000000000000000000000000000000000000000003039"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"method": "hardhat_setStorageAt", "params": ["0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56", "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49", -"0x0000000000000000000000000000000000000000000000000000000000003039"]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +"0x0000000000000000000000000000000000000000000000000000000000003039"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_serde_custom_coinbase() { let s = r#"{"method": "anvil_setCoinbase", "params": -["0x295a70b2de5e3953354a6a8344e616ed314d7251"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0x295a70b2de5e3953354a6a8344e616ed314d7251"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_serde_custom_logging() { @@ -1304,23 +1335,23 @@ serde_json::from_value::(value).unwrap(); } #[test] fn test_eth_uncle_count_by_block_hash() { - let s = r#"{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockHash","params":["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; - let value: serde_json::Value = serde_json::from_str(s).unwrap(); - let _req = serde_json::from_value::(value).unwrap(); + let s = r#"{"jsonrpc":"2.0","method":"eth_getUncleCountByBlockHash","params":["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); } #[test] fn test_eth_block_tx_count_by_block_hash() { - let s = r#"{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByHash","params":["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; - let value: serde_json::Value = serde_json::from_str(s).unwrap(); - let _req = serde_json::from_value::(value).unwrap(); + let s = r#"{"jsonrpc":"2.0","method":"eth_getBlockTransactionCountByHash","params":["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); } #[test] fn test_eth_get_logs() { - let s = r#"{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":74}"#; - let value: serde_json::Value = serde_json::from_str(s).unwrap(); - let _req = serde_json::from_value::(value).unwrap(); + let s = r#"{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"topics":["0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"]}],"id":74}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); } #[test] @@ -1333,9 +1364,10 @@ serde_json::from_value::(value).unwrap(); } #[test] fn test_serde_eth_unsubscribe() { let s = r#"{"id": 1, "method": "eth_unsubscribe", "params": -["0x9cef478923ff08bf67fde6c64013158d"]}"#; let value: serde_json::Value = -serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0x9cef478923ff08bf67fde6c64013158d"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_serde_eth_subscribe() { @@ -1345,9 +1377,9 @@ serde_json::from_value::(value).unwrap(); } let s = r#"{"id": 1, "method": "eth_subscribe", "params": ["logs", {"address": "0x8320fe7702b96808f7bbc0d4a888ed1468216cfd", "topics": -["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); +["0xd78a0cb8bb633d06981248b816e7bd33c2a35a6089241d099fa519e361cab902"]}]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"id": 1, "method": "eth_subscribe", "params": ["newPendingTransactions"]}"#; let value: serde_json::Value = serde_json::from_str(s).unwrap(); @@ -1361,18 +1393,19 @@ serde_json::from_value::(value).unwrap(); #[test] fn test_serde_debug_trace_transaction() { let s = r#"{"method": "debug_traceTransaction", "params": -["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); +["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"method": "debug_traceTransaction", "params": -["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff", {}]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); +["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff", {}]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); let s = r#"{"method": "debug_traceTransaction", "params": ["0x4a3b0fce2cb9707b0baa68640cf2fe858c8bb4121b2a8cb904ff369d38a560ff", {"disableStorage": -true}]}"#; let value: serde_json::Value = serde_json::from_str(s).unwrap(); +true}]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); let _req = serde_json::from_value::(value).unwrap(); } @@ -1402,36 +1435,37 @@ true}]}"#; let value: serde_json::Value = serde_json::from_str(s).unwrap #[test] fn test_serde_eth_storage() { let s = r#"{"method": "eth_getStorageAt", "params": -["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"]}"#; let value: -serde_json::Value = serde_json::from_str(s).unwrap(); let _req = -serde_json::from_value::(value).unwrap(); } +["0x295a70b2de5e3953354a6a8344e616ed314d7251", "0x0", "latest"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); + let _req = serde_json::from_value::(value).unwrap(); + } #[test] fn test_eth_call() { let req = r#"{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}"#; -let _req =serde_json::from_str::(req).unwrap(); + let _req = serde_json::from_str::(req).unwrap(); - let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"},"latest"]}"#; + let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"},"latest"]}"#; let _req = serde_json::from_str::(s).unwrap(); let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}]}"#; let _req = serde_json::from_str::(s).unwrap(); - let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "latest" }]}"#; + let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "latest" }]}"#; let _req = serde_json::from_str::(s).unwrap(); - let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }]}"#; + let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockNumber": "0x0" }]}"#; let _req = serde_json::from_str::(s).unwrap(); - let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockHash":"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }]}"#; - let _req = serde_json::from_str::(s).unwrap(); + let s = r#"{"method": "eth_call", "params":[{"data":"0xcfae3217","from":"0xd84de507f3fada7df80908082d3239466db55a71","to":"0xcbe828fdc46e3b1c351ec90b1a5e7d9742c0398d"}, { "blockHash":"0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3" }]}"#; + let _req = serde_json::from_str::(s).unwrap(); } #[test] fn test_serde_eth_balance() { let s = r#"{"method": "eth_getBalance", "params": -["0x295a70b2de5e3953354a6a8344e616ed314d7251", "latest"]}"#; let value: serde_json::Value -= serde_json::from_str(s).unwrap(); +["0x295a70b2de5e3953354a6a8344e616ed314d7251", "latest"]}"#; + let value: serde_json::Value = serde_json::from_str(s).unwrap(); let _req = serde_json::from_value::(value).unwrap(); } diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index c1a1675f223a..a483c0dbe1d7 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -14,7 +14,7 @@ use ethers_core::{ rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}, }, }; -use foundry_evm::traces::CallTraceArena; +use foundry_evm::traces::{CallTraceArena, CallTraceNode}; use foundry_utils::types::ToAlloy; use revm::{ interpreter::InstructionResult, @@ -26,8 +26,8 @@ use std::ops::Deref; mod ethers_compat; pub use ethers_compat::{ - call_to_internal_tx_request, from_ethers_access_list, to_alloy_proof, to_ethers_access_list, - to_internal_tx_request, to_ethers_state_override, to_alloy_state_override + call_to_internal_tx_request, from_ethers_access_list, to_alloy_proof, to_alloy_state_override, + to_ethers_access_list, to_ethers_state_override, to_internal_tx_request, }; /// The signature used to bypass signing via the `eth_sendUnsignedTransaction` cheat RPC @@ -1283,46 +1283,11 @@ pub struct TransactionInfo { pub contract_address: Option
, pub logs: Vec, pub logs_bloom: Bloom, - pub traces: CallTraceArena, + pub traces: Vec, pub exit: InstructionResult, pub out: Option, } -// === impl TransactionInfo === - -impl TransactionInfo { - /// Returns the `traceAddress` of the node in the arena - /// - /// The `traceAddress` field of all returned traces, gives the exact location in the call trace - /// [index in root, index in first CALL, index in second CALL, …]. - /// - /// # Panics - /// - /// if the `idx` does not belong to a node - pub fn trace_address(&self, idx: usize) -> Vec { - if idx == 0 { - // root call has empty traceAddress - return vec![] - } - let mut graph = vec![]; - let mut node = &self.traces.arena[idx]; - while let Some(parent) = node.parent { - // the index of the child call in the arena - let child_idx = node.idx; - node = &self.traces.arena[parent]; - // find the index of the child call in the parent node - let call_idx = node - .children - .iter() - .position(|child| *child == child_idx) - .expect("child exists in parent"); - graph.push(call_idx); - } - graph.reverse(); - graph - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index a5131b274566..9f7610bc0a53 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -9,8 +9,7 @@ use crate::{ validate::TransactionValidator, }, error::{ - BlockchainError, FeeHistoryError, InvalidTransactionError, - Result, ToRpcResponseResult, + BlockchainError, FeeHistoryError, InvalidTransactionError, Result, ToRpcResponseResult, }, fees::{FeeDetails, FeeHistoryCache}, macros::node_info, @@ -30,7 +29,6 @@ use crate::{ ClientFork, LoggingManager, Miner, MiningMode, StorageInfo, }; use alloy_primitives::{Address, Bytes, TxHash, B256, B64, U256, U64}; -use alloy_transport::TransportErrorKind; use alloy_rpc_types::{ state::StateOverride, AccessList, @@ -50,11 +48,12 @@ use alloy_rpc_types::{ TransactionRequest as AlloyTransactionRequest, TxpoolContent, TxpoolInspect, - // trace::{geth::{DefaultFrame, GethDebugTracingOptions, GethTrace}, + // trace::{geth::{DefaultFrame, GethDefaultTracingOptions, GethTrace}, // parity::LocalizedTransactionTrace}, TxpoolInspectSummary, TxpoolStatus, }; +use alloy_transport::TransportErrorKind; use anvil_core::{ eth::{ block::BlockInfo, @@ -71,16 +70,7 @@ use anvil_core::{ }, }; use anvil_rpc::{error::RpcError, response::ResponseResult}; -use ethers::{ - prelude::DefaultFrame, - types::{ - transaction::eip712::TypedData, - GethDebugTracingOptions, - GethTrace, - Trace, - }, - utils::rlp, -}; +use ethers::{types::transaction::eip712::TypedData, utils::rlp}; use foundry_common::provider::alloy::ProviderBuilder; use foundry_evm::{ backend::DatabaseError, @@ -93,6 +83,10 @@ use foundry_evm::{ use foundry_utils::types::{ToAlloy, ToEthers}; use futures::channel::{mpsc::Receiver, oneshot}; use parking_lot::RwLock; +use reth_rpc_types::trace::{ + geth::{DefaultFrame, GethDefaultTracingOptions, GethTrace}, + parity::LocalizedTransactionTrace, +}; use std::{collections::HashSet, future::Future, sync::Arc, time::Duration}; /// The client version: `anvil/v{major}.{minor}.{patch}` @@ -300,10 +294,9 @@ impl EthApi { self.anvil_auto_impersonate_account(enable).await.to_rpc_result() } EthRequest::GetAutoMine(()) => self.anvil_get_auto_mine().to_rpc_result(), - EthRequest::Mine(blocks, interval) => self - .anvil_mine(blocks, interval) - .await - .to_rpc_result(), + EthRequest::Mine(blocks, interval) => { + self.anvil_mine(blocks, interval).await.to_rpc_result() + } EthRequest::SetAutomine(enabled) => { self.anvil_set_auto_mine(enabled).await.to_rpc_result() } @@ -343,19 +336,21 @@ impl EthApi { EthRequest::AnvilMetadata(_) => self.anvil_metadata().await.to_rpc_result(), EthRequest::EvmSnapshot(_) => self.evm_snapshot().await.to_rpc_result(), EthRequest::EvmRevert(id) => self.evm_revert(id).await.to_rpc_result(), - EthRequest::EvmIncreaseTime(time) => { - self.evm_increase_time(time).await.to_rpc_result() - } + EthRequest::EvmIncreaseTime(time) => self.evm_increase_time(time).await.to_rpc_result(), EthRequest::EvmSetNextBlockTimeStamp(time) => { if time >= U256::from(u64::MAX) { - return ResponseResult::Error(RpcError::invalid_params("The timestamp is too big")) + return ResponseResult::Error(RpcError::invalid_params( + "The timestamp is too big", + )) } let time = time.to::(); self.evm_set_next_block_timestamp(time).to_rpc_result() } EthRequest::EvmSetTime(timestamp) => { if timestamp >= U256::from(u64::MAX) { - return ResponseResult::Error(RpcError::invalid_params("The timestamp is too big")) + return ResponseResult::Error(RpcError::invalid_params( + "The timestamp is too big", + )) } let time = timestamp.to::(); self.evm_set_time(time).to_rpc_result() @@ -420,10 +415,9 @@ impl EthApi { EthRequest::OtsSearchTransactionsAfter(address, num, page_size) => { self.ots_search_transactions_after(address, num, page_size).await.to_rpc_result() } - EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => self - .ots_get_transaction_by_sender_and_nonce(address, nonce) - .await - .to_rpc_result(), + EthRequest::OtsGetTransactionBySenderAndNonce(address, nonce) => { + self.ots_get_transaction_by_sender_and_nonce(address, nonce).await.to_rpc_result() + } EthRequest::OtsGetContractCreator(address) => { self.ots_get_contract_creator(address).await.to_rpc_result() } @@ -1267,11 +1261,7 @@ impl EthApi { // efficiently, instead we fetch it from the fork if fork.predates_fork_inclusive(number) { return fork - .fee_history( - block_count, - BlockNumber::Number(number), - &reward_percentiles, - ) + .fee_history(block_count, BlockNumber::Number(number), &reward_percentiles) .await .map_err(|_| BlockchainError::DataUnavailable); } @@ -1439,13 +1429,9 @@ impl EthApi { pub async fn debug_trace_transaction( &self, tx_hash: B256, - opts: GethDebugTracingOptions, + opts: GethDefaultTracingOptions, ) -> Result { node_info!("debug_traceTransaction"); - if opts.tracer.is_some() { - return Err(RpcError::invalid_params("non-default tracer not supported yet").into()); - } - self.backend.debug_trace_transaction(tx_hash, opts).await } @@ -1456,12 +1442,9 @@ impl EthApi { &self, request: CallRequest, block_number: Option, - opts: GethDebugTracingOptions, + opts: GethDefaultTracingOptions, ) -> Result { node_info!("debug_traceCall"); - if opts.tracer.is_some() { - return Err(RpcError::invalid_params("non-default tracer not supported yet").into()); - } let block_request = self.block_request(block_number).await?; let fees = FeeDetails::new( request.gas_price.map(|g| g.to_ethers()), @@ -1478,7 +1461,7 @@ impl EthApi { /// Returns traces for the transaction hash via parity's tracing endpoint /// /// Handler for RPC call: `trace_transaction` - pub async fn trace_transaction(&self, tx_hash: B256) -> Result> { + pub async fn trace_transaction(&self, tx_hash: B256) -> Result> { node_info!("trace_transaction"); self.backend.trace_transaction(tx_hash).await } @@ -1486,7 +1469,7 @@ impl EthApi { /// Returns traces for the transaction hash via parity's tracing endpoint /// /// Handler for RPC call: `trace_block` - pub async fn trace_block(&self, block: BlockNumber) -> Result> { + pub async fn trace_block(&self, block: BlockNumber) -> Result> { node_info!("trace_block"); self.backend.trace_block(block).await } @@ -1955,7 +1938,11 @@ impl EthApi { // let interval = config.provider.get_interval(); let new_provider = Arc::new( ProviderBuilder::new(&url).max_retry(10).initial_backoff(1000).build().map_err( - |_| TransportErrorKind::custom_str(format!("Failed to parse invalid url {url}").as_str()), + |_| { + TransportErrorKind::custom_str( + format!("Failed to parse invalid url {url}").as_str(), + ) + }, // TODO: Add interval )?, // .interval(interval), ); diff --git a/crates/anvil/src/eth/backend/executor.rs b/crates/anvil/src/eth/backend/executor.rs index 88fdb5387be4..a1b16c5a16f0 100644 --- a/crates/anvil/src/eth/backend/executor.rs +++ b/crates/anvil/src/eth/backend/executor.rs @@ -19,6 +19,7 @@ use ethers::{ }; use foundry_evm::{ backend::DatabaseError, + inspectors::{TracingInspector, TracingInspectorConfig}, revm, revm::{ interpreter::InstructionResult, @@ -164,7 +165,7 @@ impl<'a, DB: Db + ?Sized, Validator: TransactionValidator> TransactionExecutor<' contract_address: contract_address.map(|c| c.to_ethers()), logs, logs_bloom: *receipt.logs_bloom(), - traces: CallTraceArena { arena: traces }, + traces, exit, out: match out { Some(Output::Call(b)) => Some(ethers::types::Bytes(b.0)), @@ -311,7 +312,12 @@ impl<'a, 'b, DB: Db + ?Sized, Validator: TransactionValidator> Iterator out, gas_used, logs: logs.unwrap_or_default().into_iter().map(Into::into).collect(), - traces: inspector.tracer.unwrap_or_default().traces.arena, + traces: inspector + .tracer + .unwrap_or(TracingInspector::new(TracingInspectorConfig::all())) + .get_traces() + .clone() + .into_nodes(), }; Some(TransactionExecutionOutcome::Executed(tx)) diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index df3e4f2f9cf6..5e3126d7b613 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -12,6 +12,7 @@ use foundry_evm::{ primitives::{Address, Bytes, B256}, EVMData, }, + traces::TracingInspectorConfig, }; /// The [`revm::Inspector`] used when transacting in the evm @@ -34,15 +35,14 @@ impl Inspector { /// Configures the `Tracer` [`revm::Inspector`] pub fn with_tracing(mut self) -> Self { - self.tracer = Some(Default::default()); + self.tracer = Some(TracingInspector::new(TracingInspectorConfig::all())); self } /// Enables steps recording for `Tracer`. - pub fn with_steps_tracing(mut self) -> Self { - let tracer = self.tracer.get_or_insert_with(Default::default); - tracer.record_steps(); - self + pub fn with_steps_tracing(self) -> Self { + // todo deprecate? + self.with_tracing() } } diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 0df0aca9fde2..817a38718499 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -32,7 +32,7 @@ use crate::{ use alloy_primitives::{Address, Bloom, Bytes, TxHash, B256, B64, U128, U256, U64, U8}; use alloy_rpc_types::{ state::StateOverride, - // trace::{geth::{DefaultFrame, GethDebugTracingOptions, GethTrace}, + // trace::{geth::{DefaultFrame, GethDefaultTracingOptions, GethTrace}, // parity::LocalizedTransactionTrace}, AccessList, Block as AlloyBlock, @@ -62,11 +62,7 @@ use anvil_core::{ use anvil_rpc::error::RpcError; use ethers::{ abi::ethereum_types::BigEndianHash, - prelude::GethTraceFrame, - types::{ - transaction::eip2930::AccessList as EthersAccessList, DefaultFrame, - GethDebugTracingOptions, GethTrace, Trace, - }, + types::transaction::eip2930::AccessList as EthersAccessList, utils::{keccak256, rlp}, }; use flate2::{read::GzDecoder, write::GzEncoder, Compression}; @@ -84,6 +80,7 @@ use foundry_evm::{ SpecId, TransactTo, TxEnv, KECCAK_EMPTY, }, }, + traces::{TracingInspector, TracingInspectorConfig}, utils::{eval_to_instruction_result, halt_to_instruction_result, u256_to_h256_be}, }; use foundry_utils::types::{ToAlloy, ToEthers}; @@ -91,6 +88,10 @@ use futures::channel::mpsc::{unbounded, UnboundedSender}; use hash_db::HashDB; use itertools::Itertools; use parking_lot::{Mutex, RwLock}; +use reth_rpc_types::trace::{ + geth::{DefaultFrame, GethDefaultTracingOptions, GethTrace}, + parity::LocalizedTransactionTrace, +}; use std::{ collections::HashMap, io::{Read, Write}, @@ -1124,7 +1125,7 @@ impl Backend { request: EthTransactionRequest, fee_details: FeeDetails, block_request: Option, - opts: GethDebugTracingOptions, + opts: GethDefaultTracingOptions, ) -> Result { self.with_database_at(block_request, |state, block| { let mut inspector = Inspector::default().with_steps_tracing(); @@ -1148,7 +1149,10 @@ impl Backend { (halt_to_instruction_result(reason), gas_used, None) }, }; - let res = inspector.tracer.unwrap_or_default().traces.geth_trace(rU256::from(gas_used), opts); + let res = inspector.tracer.unwrap_or(TracingInspector::new(TracingInspectorConfig::all())).into_geth_builder().geth_traces(gas_used, match &out { + Some(out) => out.data().clone(), + None => Bytes::new() + }, opts); trace!(target: "backend", "trace call return {:?} out: {:?} gas {} on block {}", exit_reason, out, gas_used, block_number); Ok(res) }) @@ -1360,10 +1364,7 @@ impl Backend { } if let Some(fork) = self.get_fork() { - return fork - .block_by_hash(hash) - .await - .map_err(|_| BlockchainError::DataUnavailable); + return fork.block_by_hash(hash).await.map_err(|_| BlockchainError::DataUnavailable); } Ok(None) @@ -1489,8 +1490,8 @@ impl Backend { BlockNumber::Finalized => { if storage.best_number.to_ethers() > (slots_in_an_epoch.to_ethers() * 2) { *storage.hashes.get( - &(storage.best_number.to_ethers() - - (slots_in_an_epoch.to_ethers() * 2)) + &(storage.best_number.to_ethers() - + (slots_in_an_epoch.to_ethers() * 2)) .to_alloy(), )? } else { @@ -1817,7 +1818,10 @@ impl Backend { } /// Returns the traces for the given transaction - pub async fn trace_transaction(&self, hash: B256) -> Result, BlockchainError> { + pub async fn trace_transaction( + &self, + hash: B256, + ) -> Result, BlockchainError> { if let Some(traces) = self.mined_parity_trace_transaction(hash) { return Ok(traces); } @@ -1830,7 +1834,10 @@ impl Backend { } /// Returns the traces for the given transaction - pub(crate) fn mined_parity_trace_transaction(&self, hash: B256) -> Option> { + pub(crate) fn mined_parity_trace_transaction( + &self, + hash: B256, + ) -> Option> { self.blockchain.storage.read().transactions.get(&hash).map(|tx| tx.parity_traces()) } @@ -1840,7 +1847,10 @@ impl Backend { } /// Returns the traces for the given block - pub(crate) fn mined_parity_trace_block(&self, block: u64) -> Option> { + pub(crate) fn mined_parity_trace_block( + &self, + block: u64, + ) -> Option> { let block = self.get_block(block)?; let mut traces = vec![]; let storage = self.blockchain.storage.read(); @@ -1854,29 +1864,32 @@ impl Backend { pub async fn debug_trace_transaction( &self, hash: B256, - opts: GethDebugTracingOptions, + opts: GethDefaultTracingOptions, ) -> Result { if let Some(traces) = self.mined_geth_trace_transaction(hash, opts.clone()) { - return Ok(GethTrace::Known(GethTraceFrame::Default(traces))); + return Ok(GethTrace::Default(traces)); } // if let Some(fork) = self.get_fork() { // return Ok(fork.debug_trace_transaction(hash, opts).await.map_err(|_| // BlockchainError::DataUnavailable)?) } - Ok(GethTrace::Known(GethTraceFrame::Default(Default::default()))) + Ok(GethTrace::Default(Default::default())) } fn mined_geth_trace_transaction( &self, hash: B256, - opts: GethDebugTracingOptions, + opts: GethDefaultTracingOptions, ) -> Option { self.blockchain.storage.read().transactions.get(&hash).map(|tx| tx.geth_trace(opts)) } /// Returns the traces for the given block - pub async fn trace_block(&self, block: BlockNumber) -> Result, BlockchainError> { + pub async fn trace_block( + &self, + block: BlockNumber, + ) -> Result, BlockchainError> { let number = self.convert_block_number(Some(block)); if let Some(traces) = self.mined_parity_trace_block(number) { return Ok(traces); @@ -2276,8 +2289,8 @@ impl TransactionValidator for Backend { if chain_id.to::() != tx_chain_id { if let Some(legacy) = tx.as_legacy() { // - if env.cfg.spec_id >= SpecId::SPURIOUS_DRAGON - && !legacy.meets_eip155(chain_id.to::()) + if env.cfg.spec_id >= SpecId::SPURIOUS_DRAGON && + !legacy.meets_eip155(chain_id.to::()) { warn!(target: "backend", ?chain_id, ?tx_chain_id, "incompatible EIP155-based V"); return Err(InvalidTransactionError::IncompatibleEIP155); @@ -2378,10 +2391,7 @@ pub fn transaction_build( let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas.map(|g| g.to::()).unwrap_or(U256::ZERO); transaction.gas_price = Some( - base_fee - .checked_add(max_priority_fee_per_gas) - .unwrap_or(U256::MAX) - .to::(), + base_fee.checked_add(max_priority_fee_per_gas).unwrap_or(U256::MAX).to::(), ); } } else { diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index 301e20b76542..810c905ca519 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -13,13 +13,20 @@ use anvil_core::eth::{ receipt::TypedReceipt, transaction::{MaybeImpersonatedTransaction, TransactionInfo}, }; -use ethers::{ - prelude::{DefaultFrame, Trace}, - types::{ActionType, GethDebugTracingOptions}, +use ethers::{prelude::Trace, types::ActionType}; +use foundry_evm::{ + revm::{interpreter::InstructionResult, primitives::Env}, + traces::{GethTraceBuilder, ParityTraceBuilder, TracingInspectorConfig}, }; -use foundry_evm::revm::{interpreter::InstructionResult, primitives::Env}; use foundry_utils::types::{ToAlloy, ToEthers}; use parking_lot::RwLock; +use reth_rpc_types::{ + trace::{ + geth::{DefaultFrame, GethDefaultTracingOptions}, + parity::LocalizedTransactionTrace, + }, + transaction::TransactionInfo as RethTransactionInfo, +}; use std::{ collections::{HashMap, VecDeque}, fmt, @@ -396,38 +403,28 @@ pub struct MinedTransaction { impl MinedTransaction { /// Returns the traces of the transaction for `trace_transaction` - pub fn parity_traces(&self) -> Vec { - let mut traces = Vec::with_capacity(self.info.traces.arena.len()); - for (idx, node) in self.info.traces.arena.iter().cloned().enumerate() { - let action = node.parity_action(); - let result = node.parity_result(); - - let action_type = if node.status() == InstructionResult::SelfDestruct { - ActionType::Suicide - } else { - node.kind().into() - }; - - let trace = Trace { - action, - result: Some(result), - trace_address: self.info.trace_address(idx), - subtraces: node.children.len(), - transaction_position: Some(self.info.transaction_index as usize), - transaction_hash: Some(self.info.transaction_hash), - block_number: self.block_number, - block_hash: self.block_hash.to_ethers(), - action_type, - error: None, - }; - traces.push(trace) - } - - traces + pub fn parity_traces(&self) -> Vec { + ParityTraceBuilder::new( + self.info.traces.clone(), + None, + TracingInspectorConfig::default_parity(), + ) + .into_localized_transaction_traces(RethTransactionInfo { + hash: Some(self.info.transaction_hash.to_alloy()), + index: Some(self.info.transaction_index as u64), + block_hash: Some(self.block_hash), + block_number: Some(self.block_number), + base_fee: None, + }) } - pub fn geth_trace(&self, opts: GethDebugTracingOptions) -> DefaultFrame { - self.info.traces.geth_trace(self.receipt.gas_used().to_alloy(), opts) + pub fn geth_trace(&self, opts: GethDefaultTracingOptions) -> DefaultFrame { + GethTraceBuilder::new(self.info.traces.clone(), TracingInspectorConfig::default_geth()) + .geth_traces( + self.receipt.gas_used().as_u64(), + Bytes::from(self.info.out.clone().unwrap_or_default().to_vec()), + opts, + ) } } diff --git a/crates/anvil/src/eth/otterscan/api.rs b/crates/anvil/src/eth/otterscan/api.rs index 219122d60704..a138ae8bc59c 100644 --- a/crates/anvil/src/eth/otterscan/api.rs +++ b/crates/anvil/src/eth/otterscan/api.rs @@ -9,9 +9,11 @@ use crate::eth::{ }; use alloy_primitives::{Address, Bytes, B256, U256, U64}; use alloy_rpc_types::{Block, BlockId, BlockNumberOrTag as BlockNumber, Transaction}; -use ethers::types::{Action, Call, Create, CreateResult, Res, Reward}; use foundry_utils::types::ToAlloy; use itertools::Itertools; +use reth_rpc_types::trace::parity::{ + Action, CallAction, CreateAction, CreateOutput, RewardAction, TraceOutput, +}; impl EthApi { /// Otterscan currently requires this endpoint, even though it's not part of the ots_* @@ -150,11 +152,11 @@ impl EthApi { let hashes = traces .into_iter() .rev() - .filter_map(|trace| match trace.action { - Action::Call(Call { from, to, .. }) - if from.to_alloy() == address || to.to_alloy() == address => + .filter_map(|trace| match trace.trace.action { + Action::Call(CallAction { from, to, .. }) + if from == address || to == address => { - trace.transaction_hash.map(|t| t.to_alloy()) + trace.transaction_hash } _ => None, }) @@ -203,17 +205,17 @@ impl EthApi { let hashes = traces .into_iter() .rev() - .filter_map(|trace| match trace.action { - Action::Call(Call { from, to, .. }) - if from.to_alloy() == address || to.to_alloy() == address => + .filter_map(|trace| match trace.trace.action { + Action::Call(CallAction { from, to, .. }) + if from == address || to == address => { - trace.transaction_hash.map(|t| t.to_alloy()) + trace.transaction_hash } - Action::Create(Create { from, .. }) if from.to_alloy() == address => { - trace.transaction_hash.map(|t| t.to_alloy()) + Action::Create(CreateAction { from, .. }) if from == address => { + trace.transaction_hash } - Action::Reward(Reward { author, .. }) if author.to_alloy() == address => { - trace.transaction_hash.map(|t| t.to_alloy()) + Action::Reward(RewardAction { author, .. }) if author == address => { + trace.transaction_hash } _ => None, }) @@ -271,14 +273,14 @@ impl EthApi { for n in (from..=to).rev() { if let Some(traces) = self.backend.mined_parity_trace_block(n) { for trace in traces.into_iter().rev() { - match (trace.action, trace.result) { + match (trace.trace.action, trace.trace.result) { ( - Action::Create(Create { from, .. }), - Some(Res::Create(CreateResult { address, .. })), - ) if address.to_alloy() == addr => { + Action::Create(CreateAction { from, .. }), + Some(TraceOutput::Create(CreateOutput { address, .. })), + ) if address == addr => { return Ok(Some(OtsContractCreator { - hash: trace.transaction_hash.unwrap().to_alloy(), - creator: from.to_alloy(), + hash: trace.transaction_hash.unwrap(), + creator: from, })) } _ => {} diff --git a/crates/anvil/src/eth/otterscan/types.rs b/crates/anvil/src/eth/otterscan/types.rs index 49ce78a70152..7cf1f87ac2af 100644 --- a/crates/anvil/src/eth/otterscan/types.rs +++ b/crates/anvil/src/eth/otterscan/types.rs @@ -4,10 +4,9 @@ use crate::eth::{ }; use alloy_primitives::{Address, Bytes, B256, U256 as rU256, U256}; use alloy_rpc_types::{Block, BlockTransactions, Transaction, TransactionReceipt}; -use ethers::types::{Action, CallType, Trace}; -use foundry_evm::{revm::interpreter::InstructionResult, utils::CallKind}; -use foundry_utils::types::ToAlloy; +use foundry_evm::{revm::interpreter::InstructionResult, traces::CallKind}; use futures::future::join_all; +use reth_rpc_types::trace::parity::{Action, CallType, LocalizedTransactionTrace}; use serde::Serialize; use serde_repr::Serialize_repr; @@ -183,11 +182,16 @@ impl OtsBlockTransactions { BlockTransactions::Uncle => return Err(BlockchainError::DataUnavailable), }; - let block_txs = block_txs.into_iter().skip(page * page_size).take(page_size).collect::>(); + let block_txs = + block_txs.into_iter().skip(page * page_size).take(page_size).collect::>(); block.transactions = match block.transactions { - BlockTransactions::Full(txs) => BlockTransactions::Full(txs.into_iter().skip(page * page_size).take(page_size).collect()), - BlockTransactions::Hashes(txs) => BlockTransactions::Hashes(txs.into_iter().skip(page * page_size).take(page_size).collect()), + BlockTransactions::Full(txs) => BlockTransactions::Full( + txs.into_iter().skip(page * page_size).take(page_size).collect(), + ), + BlockTransactions::Hashes(txs) => BlockTransactions::Hashes( + txs.into_iter().skip(page * page_size).take(page_size).collect(), + ), BlockTransactions::Uncle => return Err(BlockchainError::DataUnavailable), }; @@ -258,10 +262,9 @@ impl OtsInternalOperation { traces .info .traces - .arena .iter() .filter_map(|node| { - match (node.kind(), node.status()) { + match (node.trace.kind, node.trace.status) { (CallKind::Call, _) if node.trace.value != rU256::ZERO => Some(Self { r#type: OtsInternalOperationType::Transfer, from: node.trace.caller, @@ -299,18 +302,18 @@ impl OtsInternalOperation { impl OtsTrace { /// Converts the list of traces for a transaction into the expected Otterscan format, as /// specified in the [`ots_traceTransaction`](https://github.com/otterscan/otterscan/blob/develop/docs/custom-jsonrpc.md#ots_tracetransaction) spec - pub fn batch_build(traces: Vec) -> Vec { + pub fn batch_build(traces: Vec) -> Vec { traces .into_iter() - .filter_map(|trace| match trace.action { + .filter_map(|trace| match trace.trace.action { Action::Call(call) => { if let Ok(ots_type) = call.call_type.try_into() { Some(OtsTrace { r#type: ots_type, - depth: trace.trace_address.len(), - from: call.from.to_alloy(), - to: call.to.to_alloy(), - value: call.value.to_alloy(), + depth: trace.trace.trace_address.len(), + from: call.from, + to: call.to, + value: call.value, input: call.input.0.into(), }) } else { @@ -318,7 +321,7 @@ impl OtsTrace { } } Action::Create(_) => None, - Action::Suicide(_) => None, + Action::Selfdestruct(_) => None, Action::Reward(_) => None, }) .collect() diff --git a/crates/chisel/src/dispatcher.rs b/crates/chisel/src/dispatcher.rs index 26f13933b049..251f964e5d0e 100644 --- a/crates/chisel/src/dispatcher.rs +++ b/crates/chisel/src/dispatcher.rs @@ -15,7 +15,7 @@ use foundry_evm::{ decode::decode_console_logs, traces::{ identifier::{EtherscanIdentifier, SignaturesIdentifier}, - CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, + render_trace, render_trace_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, }, }; use once_cell::sync::Lazy; @@ -985,11 +985,10 @@ impl ChiselDispatcher { } println!("{}", Paint::green("Traces:")); - for (kind, trace) in &mut result.traces { + for (kind, trace) in &result.traces { // Display all Setup + Execution traces. if matches!(kind, TraceKind::Setup | TraceKind::Execution) { - decoder.decode(trace).await; - println!("{trace}"); + println!("{}", render_trace_arena(trace, decoder).await?); } } diff --git a/crates/cli/src/utils/cmd.rs b/crates/cli/src/utils/cmd.rs index 309e4d295606..638702802a9c 100644 --- a/crates/cli/src/utils/cmd.rs +++ b/crates/cli/src/utils/cmd.rs @@ -17,7 +17,7 @@ use foundry_evm::{ opts::EvmOpts, traces::{ identifier::{EtherscanIdentifier, SignaturesIdentifier}, - CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, Traces, + render_trace_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, Traces, }, }; use std::{fmt::Write, path::PathBuf, str::FromStr}; @@ -417,20 +417,15 @@ pub async fn handle_traces( pub async fn print_traces( result: &mut TraceResult, decoder: &CallTraceDecoder, - verbose: bool, + _verbose: bool, ) -> Result<()> { if result.traces.is_empty() { panic!("No traces found") } println!("Traces:"); - for (_, trace) in &mut result.traces { - decoder.decode(trace).await; - if !verbose { - println!("{trace}"); - } else { - println!("{trace:#}"); - } + for (_, arena) in &result.traces { + println!("{}", render_trace_arena(arena, decoder).await?); } println!(); diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 4cbdcdb3d813..ddb0770720d0 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -528,7 +528,7 @@ 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: U256::from(0), + basefee: U256::ZERO, gas_limit: self.gas_limit, ..self.env.block.clone() }, @@ -538,7 +538,7 @@ impl Executor { data, value, // As above, we set the gas price to 0. - gas_price: U256::from(0), + gas_price: U256::ZERO, gas_priority_fee: None, gas_limit: self.gas_limit.to(), ..self.env.tx.clone() diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index d95d24d68b3c..9a26da616e46 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -315,7 +315,7 @@ impl InspectorStack { cheatcodes.labels.clone().into_iter().map(|l| (l.0, l.1)).collect() }) .unwrap_or_default(), - traces: self.tracer.map(|tracer| tracer.traces), + traces: self.tracer.map(|tracer| tracer.get_traces().clone()), debug: self.debugger.map(|debugger| debugger.arena), coverage: self.coverage.map(|coverage| coverage.maps), script_wallets: self diff --git a/crates/evm/fuzz/src/lib.rs b/crates/evm/fuzz/src/lib.rs index 62181c2300c9..72fded966fb5 100644 --- a/crates/evm/fuzz/src/lib.rs +++ b/crates/evm/fuzz/src/lib.rs @@ -49,6 +49,7 @@ pub struct BaseCounterExample { /// Contract name if it exists pub contract_name: Option, /// Traces + #[serde(skip)] pub traces: Option, #[serde(skip)] pub args: Vec, diff --git a/crates/evm/traces/Cargo.toml b/crates/evm/traces/Cargo.toml index a9c713964fcd..9a8d747eb3d0 100644 --- a/crates/evm/traces/Cargo.toml +++ b/crates/evm/traces/Cargo.toml @@ -23,7 +23,7 @@ alloy-json-abi.workspace = true alloy-primitives = { workspace = true, features = ["serde", "getrandom", "arbitrary", "rlp"] } alloy-sol-types.workspace = true revm.workspace = true -reth-revm-inspectors = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/tracer-snapshot-type" } +reth-revm-inspectors = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/trace-builder" } ethers-core.workspace = true diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index ccb9d47c0b07..9d94f8bcd1fd 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -1,10 +1,10 @@ use crate::{ identifier::{AddressIdentity, SingleSignaturesIdentifier, TraceIdentifier}, - utils, CallTrace, CallTraceArena, TraceCallData, TraceLog, TraceRetData, + utils, CallTrace, CallTraceArena, DecodedCallData, DecodedCallTrace, }; use alloy_dyn_abi::{DecodedEvent, DynSolValue, EventExt, FunctionExt, JsonAbiExt}; use alloy_json_abi::{Event, Function, JsonAbi as Abi}; -use alloy_primitives::{Address, Selector, B256}; +use alloy_primitives::{Address, Log, Selector, B256}; use foundry_common::{abi::get_indexed_event, fmt::format_token, SELECTOR_LEN}; use foundry_evm_core::{ abi::{CONSOLE_ABI, HARDHAT_CONSOLE_ABI, HEVM_ABI}, @@ -165,11 +165,24 @@ impl CallTraceDecoder { #[inline(always)] fn addresses<'a>( &'a self, - trace: &'a CallTraceArena, + arena: &'a CallTraceArena, ) -> impl Iterator)> + 'a { - trace.addresses().into_iter().filter(|&(address, _)| { - !self.labels.contains_key(address) || !self.contracts.contains_key(address) - }) + arena + .nodes() + .iter() + .map(|node| { + ( + &node.trace.address, + if node.trace.kind == crate::CallKind::Create { + Some(node.trace.data.as_ref()) + } else { + None + }, + ) + }) + .filter(|(address, _)| { + !self.labels.contains_key(*address) || !self.contracts.contains_key(*address) + }) } fn collect_identities(&mut self, identities: Vec>) { @@ -217,41 +230,31 @@ impl CallTraceDecoder { } } - /// Decodes all nodes in the specified call trace. - pub async fn decode(&self, traces: &mut CallTraceArena) { - for node in &mut traces.arena { - self.decode_function(&mut node.trace).await; - for log in node.logs.iter_mut() { - self.decode_event(log).await; - } - } - } - - async fn decode_function(&self, trace: &mut CallTrace) { + pub async fn decode_function(&self, trace: &CallTrace) -> DecodedCallTrace { + // todo: avoid decoding creates // Decode precompile - if precompiles::decode(trace, 1) { - return + if let Some((label, func)) = precompiles::decode(&trace, 1) { + return DecodedCallTrace { label: Some(label), return_data: None, func: Some(func) } } // Set label - if trace.label.is_none() { - if let Some(label) = self.labels.get(&trace.address) { - trace.label = Some(label.clone()); - } - } + let label = self.labels.get(&trace.address).cloned(); // Set contract name - if trace.contract.is_none() { + // todo + /*if trace.contract.is_none() { if let Some(contract) = self.contracts.get(&trace.address) { trace.contract = Some(contract.clone()); } - } - - let TraceCallData::Raw(cdata) = &trace.data else { return }; + }*/ + let cdata = &trace.data; if trace.address == DEFAULT_CREATE2_DEPLOYER { - trace.data = TraceCallData::Decoded { signature: "create2".to_string(), args: vec![] }; - return + return DecodedCallTrace { + label, + return_data: None, + func: Some(DecodedCallData { signature: "create2".to_string(), args: vec![] }), + }; } if cdata.len() >= SELECTOR_LEN { @@ -270,48 +273,56 @@ impl CallTraceDecoder { &functions } }; - let [func, ..] = &functions[..] else { return }; - self.decode_function_input(trace, func); - self.decode_function_output(trace, functions); + let [func, ..] = &functions[..] else { + return DecodedCallTrace { label, return_data: None, func: None } + }; + + DecodedCallTrace { + label, + func: Some(self.decode_function_input(&trace, func)), + return_data: self.decode_function_output(&trace, functions), + } } else { let has_receive = self.receive_contracts.contains(&trace.address); let signature = if cdata.is_empty() && has_receive { "receive()" } else { "fallback()" }.into(); let args = if cdata.is_empty() { Vec::new() } else { vec![cdata.to_string()] }; - trace.data = TraceCallData::Decoded { signature, args }; - if let TraceRetData::Raw(rdata) = &trace.output { - if !trace.success { - trace.output = TraceRetData::Decoded(decode::decode_revert( - rdata, + DecodedCallTrace { + label, + return_data: if !trace.success { + Some(decode::decode_revert( + &trace.output, Some(&self.errors), Some(trace.status), - )); - } + )) + } else { + None + }, + func: Some(DecodedCallData { signature, args }), } } } /// Decodes a function's input into the given trace. - fn decode_function_input(&self, trace: &mut CallTrace, func: &Function) { - let TraceCallData::Raw(data) = &trace.data else { return }; + fn decode_function_input(&self, trace: &CallTrace, func: &Function) -> DecodedCallData { let mut args = None; - if data.len() >= SELECTOR_LEN { + if trace.data.len() >= SELECTOR_LEN { if trace.address == CHEATCODE_ADDRESS { // Try to decode cheatcode inputs in a more custom way - if let Some(v) = self.decode_cheatcode_inputs(func, data) { + if let Some(v) = self.decode_cheatcode_inputs(func, &trace.data) { args = Some(v); } } if args.is_none() { - if let Ok(v) = func.abi_decode_input(&data[SELECTOR_LEN..], false) { + if let Ok(v) = func.abi_decode_input(&trace.data[SELECTOR_LEN..], false) { args = Some(v.iter().map(|value| self.apply_label(value)).collect()); } } } - trace.data = - TraceCallData::Decoded { signature: func.signature(), args: args.unwrap_or_default() }; + + DecodedCallData { signature: func.signature(), args: args.unwrap_or_default() } } /// Custom decoding for cheatcode inputs. @@ -380,15 +391,14 @@ impl CallTraceDecoder { } /// Decodes a function's output into the given trace. - fn decode_function_output(&self, trace: &mut CallTrace, funcs: &[Function]) { - let TraceRetData::Raw(data) = &trace.output else { return }; + fn decode_function_output(&self, trace: &CallTrace, funcs: &[Function]) -> Option { + let data = &trace.output; if trace.success { if trace.address == CHEATCODE_ADDRESS { if let Some(decoded) = funcs.iter().find_map(|func| self.decode_cheatcode_outputs(func)) { - trace.output = TraceRetData::Decoded(decoded); - return + return Some(decoded) } } @@ -398,18 +408,17 @@ impl CallTraceDecoder { // Functions coming from an external database do not have any outputs specified, // and will lead to returning an empty list of values. if values.is_empty() { - return + return None } - trace.output = TraceRetData::Decoded( + + return Some( values.iter().map(|value| self.apply_label(value)).format(", ").to_string(), - ); + ) } + + None } else { - trace.output = TraceRetData::Decoded(decode::decode_revert( - data, - Some(&self.errors), - Some(trace.status), - )); + Some(decode::decode_revert(data, Some(&self.errors), Some(trace.status))) } } @@ -426,8 +435,8 @@ impl CallTraceDecoder { } /// Decodes an event. - async fn decode_event(&self, log: &mut TraceLog) { - let TraceLog::Raw(raw_log) = log else { return }; + async fn decode_event(&self, log: &Log) { + /*let TraceLog::Raw(raw_log) = log else { return }; let &[t0, ..] = raw_log.topics() else { return }; let mut events = Vec::new(); @@ -459,7 +468,8 @@ impl CallTraceDecoder { ); break } - } + }*/ + // todo } fn apply_label(&self, value: &DynSolValue) -> String { diff --git a/crates/evm/traces/src/decoder/precompiles.rs b/crates/evm/traces/src/decoder/precompiles.rs index a1b3f9425034..047a737da59f 100644 --- a/crates/evm/traces/src/decoder/precompiles.rs +++ b/crates/evm/traces/src/decoder/precompiles.rs @@ -1,4 +1,4 @@ -use crate::{CallTrace, TraceCallData}; +use crate::{CallTrace, DecodedCallData}; use alloy_primitives::{B256, U256}; use alloy_sol_types::{abi, sol, SolCall}; use itertools::Itertools; @@ -36,20 +36,20 @@ macro_rules! tri { ($e:expr) => { match $e { Ok(x) => x, - Err(_) => return false, + Err(_) => return None, } }; } -/// Tries to decode a precompile call. Returns `true` if successful. -pub(super) fn decode(trace: &mut CallTrace, _chain_id: u64) -> bool { +/// Tries to decode a precompile call. Returns `Some` if successful. +pub(super) fn decode(trace: &CallTrace, _chain_id: u64) -> Option<(String, DecodedCallData)> { let [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, x @ 0x01..=0x0a] = trace.address.0 .0 else { - return false + return None }; - let TraceCallData::Raw(data) = &trace.data else { return false }; + let data = &trace.data; let (signature, args) = match x { 0x01 => { @@ -75,11 +75,7 @@ pub(super) fn decode(trace: &mut CallTrace, _chain_id: u64) -> bool { }; // TODO: Other chain precompiles - - trace.data = TraceCallData::Decoded { signature: signature.to_string(), args }; - trace.label = Some("PRECOMPILES".into()); - - true + Some(("PRECOMPILES".into(), DecodedCallData { signature: signature.to_string(), args })) } // Note: we use the ABI decoder, but this is not necessarily ABI-encoded data. It's just a diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index f182ee7a213b..449e594683c3 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -7,19 +7,12 @@ #[macro_use] extern crate tracing; -use alloy_primitives::{Address, Bytes, Log as RawLog, B256, U256}; -use ethers_core::types::{DefaultFrame, GethDebugTracingOptions, StructLog}; +use alloy_primitives::U256; use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact}; -use foundry_evm_core::{constants::CHEATCODE_ADDRESS, debug::Instruction, utils::CallKind}; -use foundry_utils::types::ToEthers; -use hashbrown::HashMap; -use itertools::Itertools; -use revm::interpreter::{opcode, CallContext, InstructionResult, SharedMemory, Stack}; +use foundry_evm_core::constants::CHEATCODE_ADDRESS; +use futures::{future::BoxFuture, FutureExt}; use serde::{Deserialize, Serialize}; -use std::{ - collections::{BTreeMap, HashSet}, - fmt, -}; +use std::{collections::BTreeMap, fmt::Write}; use yansi::{Color, Paint}; /// Call trace address identifiers. @@ -31,21 +24,181 @@ use identifier::LocalTraceIdentifier; mod decoder; pub use decoder::{CallTraceDecoder, CallTraceDecoderBuilder}; +use reth_revm_inspectors::tracing::types::LogCallOrder; pub use reth_revm_inspectors::tracing::{ - types::{CallTrace, CallTraceNode}, - CallTraceArena, StackSnapshotType, TracingInspector, TracingInspectorConfig, + types::{CallKind, CallTrace, CallTraceNode}, + CallTraceArena, GethTraceBuilder, ParityTraceBuilder, StackSnapshotType, TracingInspector, + TracingInspectorConfig, }; pub mod utils; pub type Traces = Vec<(TraceKind, CallTraceArena)>; +#[derive(Default)] +pub struct DecodedCallData { + pub signature: String, + pub args: Vec, +} + +#[derive(Default)] +pub struct DecodedCallTrace { + pub label: Option, + pub return_data: Option, + pub func: Option, +} + const PIPE: &str = " │ "; const EDGE: &str = " └─ "; const BRANCH: &str = " ├─ "; const CALL: &str = "→ "; const RETURN: &str = "← "; +/// Render a collection of call traces. +/// +/// The traces will be decoded using the given decoder, if possible. +pub async fn render_trace_arena( + arena: &CallTraceArena, + decoder: &CallTraceDecoder, +) -> Result { + fn inner<'a>( + arena: &'a [CallTraceNode], + decoder: &'a CallTraceDecoder, + s: &'a mut String, + idx: usize, + left: &'a str, + child: &'a str, + ) -> BoxFuture<'a, Result<(), std::fmt::Error>> { + async move { + let node = &arena[idx]; + + // Display trace header + let (trace, return_data) = render_trace(&node.trace, decoder).await?; + writeln!(s, "{}", trace)?; + + // Display logs and subcalls + let left_prefix = format!("{child}{BRANCH}"); + let right_prefix = format!("{child}{PIPE}"); + for child in &node.ordering { + match child { + LogCallOrder::Log(index) => { + /*let log = node.logs[*index].to_string(); + // Prepend our tree structure symbols to each line of the displayed log + log.lines().enumerate().try_for_each(|(i, line)| { + // todo: render log/decode log + writeln!( + s, + "{}{}", + if i == 0 { &left_prefix } else { &right_prefix }, + line + ) + })?;*/ + // todo + } + LogCallOrder::Call(index) => { + inner( + arena, + decoder, + s, + node.children[*index], + &left_prefix, + &right_prefix, + ) + .await?; + } + } + } + + // Display trace return data + let color = trace_color(&node.trace); + write!(s, "{child}{EDGE}{}", color.paint(RETURN))?; + if node.trace.kind.is_any_create() { + match &return_data { + None => { + writeln!(s, "{} bytes of code", node.trace.data.len())?; + } + Some(val) => { + writeln!(s, "{val}")?; + } + } + } else { + writeln!(s, "{}", node.trace.output)?; + } + + Ok(()) + } + .boxed() + } + + let mut s = String::new(); + inner(arena.nodes(), decoder, &mut s, 0, " ", " ").await?; + Ok(s) +} + +/// Render a call trace. +/// +/// The trace will be decoded using the given decoder, if possible. +pub async fn render_trace( + trace: &CallTrace, + decoder: &CallTraceDecoder, +) -> Result<(String, Option), std::fmt::Error> { + let mut s = String::new(); + write!(&mut s, "[{}]", trace.gas_used)?; + let address = trace.address.to_checksum(None); + + let decoded = decoder.decode_function(trace).await; + if trace.kind.is_any_create() { + write!( + &mut s, + "{}{} {}@{}", + Paint::yellow(CALL), + Paint::yellow("new"), + decoded.label.as_deref().unwrap_or(""), + address + )?; + } else { + let (func_name, inputs) = match &decoded.func { + Some(DecodedCallData { signature, args }) => { + let name = signature.split('(').next().unwrap(); + (name.to_string(), args.join(", ")) + } + None => { + debug!(target: "evm::traces", trace=?trace, "unhandled raw calldata"); + if trace.data.len() < 4 { + ("fallback".to_string(), hex::encode(&trace.data)) + } else { + let (selector, data) = trace.data.split_at(4); + (hex::encode(selector), hex::encode(data)) + } + } + }; + + let action = match trace.kind { + CallKind::Call => "", + CallKind::StaticCall => " [staticcall]", + CallKind::CallCode => " [callcode]", + CallKind::DelegateCall => " [delegatecall]", + CallKind::Create | CallKind::Create2 => unreachable!(), + }; + + let color = trace_color(trace); + write!( + &mut s, + "{addr}::{func_name}{opt_value}({inputs}){action}", + addr = color.paint(decoded.label.as_deref().unwrap_or(&address)), + func_name = color.paint(func_name), + opt_value = if trace.value == U256::ZERO { + String::new() + } else { + format!("{{value: {}}}", trace.value) + }, + action = Paint::yellow(action), + )?; + } + + Ok((s, decoded.return_data)) +} + /// Specifies the kind of trace. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum TraceKind { diff --git a/crates/forge/bin/cmd/script/executor.rs b/crates/forge/bin/cmd/script/executor.rs index 66cb5440e408..dc2a7fb1983e 100644 --- a/crates/forge/bin/cmd/script/executor.rs +++ b/crates/forge/bin/cmd/script/executor.rs @@ -167,12 +167,12 @@ impl ScriptArgs { .traces .iter() .flat_map(|(_, traces)| { - traces.arena.iter().filter_map(|node| { - if matches!(node.kind(), CallKind::Create | CallKind::Create2) { + traces.nodes().iter().filter_map(|node| { + if node.trace.kind.is_any_create() { return Some(AdditionalContract { - opcode: node.kind(), + opcode: node.trace.kind, address: node.trace.address, - init_code: node.trace.data.as_bytes().to_vec(), + init_code: node.trace.data.to_vec(), }); } None @@ -230,9 +230,8 @@ impl ScriptArgs { ); } - for (_kind, trace) in &mut traces { - decoder.decode(trace).await; - println!("{trace}"); + for (_, trace) in &traces { + println!("{}", render_trace_arena(trace, decoder).await?); } } diff --git a/crates/forge/bin/cmd/script/mod.rs b/crates/forge/bin/cmd/script/mod.rs index 10f3e48739e7..bb85ea429907 100644 --- a/crates/forge/bin/cmd/script/mod.rs +++ b/crates/forge/bin/cmd/script/mod.rs @@ -18,7 +18,7 @@ use forge::{ opts::EvmOpts, traces::{ identifier::{EtherscanIdentifier, LocalTraceIdentifier, SignaturesIdentifier}, - CallTraceDecoder, CallTraceDecoderBuilder, TraceCallData, TraceKind, TraceRetData, Traces, + render_trace_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, Traces, }, utils::CallKind, }; @@ -304,7 +304,7 @@ impl ScriptArgs { } shell::println("Traces:")?; - for (kind, trace) in &mut result.traces { + for (kind, trace) in &result.traces { let should_include = match kind { TraceKind::Setup => verbosity >= 5, TraceKind::Execution => verbosity > 3, @@ -312,8 +312,7 @@ impl ScriptArgs { } || !result.success; if should_include { - decoder.decode(trace).await; - shell::println(format!("{trace}"))?; + shell::println(format!("{}", render_trace_arena(trace, decoder).await?))?; } } shell::println(String::new())?; @@ -511,27 +510,17 @@ impl ScriptArgs { // From traces let create_nodes = result.traces.iter().flat_map(|(_, traces)| { - traces - .arena - .iter() - .filter(|node| matches!(node.kind(), CallKind::Create | CallKind::Create2)) + traces.nodes().iter().filter(|node| node.trace.kind.is_any_create()) }); let mut unknown_c = 0usize; for node in create_nodes { - // Calldata == init code - if let TraceCallData::Raw(ref init_code) = node.trace.data { - // Output is the runtime code - if let TraceRetData::Raw(ref deployed_code) = node.trace.output { - // Only push if it was not present already - if !bytecodes.iter().any(|(_, b, _)| *b == init_code.as_ref()) { - bytecodes.push((format!("Unknown{unknown_c}"), init_code, deployed_code)); - unknown_c += 1; - } - continue; - } + let init_code = &node.trace.data; + let deployed_code = &node.trace.output; + if !bytecodes.iter().any(|(_, b, _)| *b == init_code.as_ref()) { + bytecodes.push((format!("Unknown{unknown_c}"), init_code, deployed_code)); + unknown_c += 1; } - // Both should be raw and not decoded since it's just bytecode - eyre::bail!("Create node returned decoded data: {:?}", node); + continue; } let mut prompt_user = false; @@ -579,9 +568,9 @@ impl ScriptArgs { } // Only prompt if we're broadcasting and we've not disabled interactivity. - if prompt_user - && !self.non_interactive - && !Confirm::new().with_prompt("Do you wish to continue?".to_string()).interact()? + if prompt_user && + !self.non_interactive && + !Confirm::new().with_prompt("Do you wish to continue?".to_string()).interact()? { eyre::bail!("User canceled the script."); } @@ -701,9 +690,7 @@ impl ScriptConfig { if let Ok(provider) = ethers_providers::Provider::::try_from(rpc) { match provider.get_chainid().await { Ok(chain_id) => match TryInto::::try_into(chain_id) { - Ok(chain) => { - return Some((SHANGHAI_ENABLED_CHAINS.contains(&chain), chain)) - } + Ok(chain) => return Some((SHANGHAI_ENABLED_CHAINS.contains(&chain), chain)), Err(_) => return None, }, Err(_) => return None, diff --git a/crates/forge/bin/cmd/script/runner.rs b/crates/forge/bin/cmd/script/runner.rs index 7035c44de775..7814e0004b5e 100644 --- a/crates/forge/bin/cmd/script/runner.rs +++ b/crates/forge/bin/cmd/script/runner.rs @@ -241,7 +241,8 @@ impl ScriptRunner { traces: traces .map(|mut traces| { // Manually adjust gas for the trace to add back the stipend/real used gas - traces.arena[0].trace.gas_cost = gas_used; + // todo(onbjerg): not possible + //traces.arena[0].trace.gas_cost = gas_used; vec![(TraceKind::Execution, traces)] }) .unwrap_or_default(), @@ -302,7 +303,8 @@ impl ScriptRunner { traces: traces .map(|mut traces| { // Manually adjust gas for the trace to add back the stipend/real used gas - traces.arena[0].trace.gas_cost = gas_used; + // todo(onbjerg): not possible + //traces.arena[0].trace.gas_cost = gas_used; vec![(TraceKind::Execution, traces)] }) .unwrap_or_default(), diff --git a/crates/forge/bin/cmd/script/transaction.rs b/crates/forge/bin/cmd/script/transaction.rs index 6dcdc9e65467..c53aaab25016 100644 --- a/crates/forge/bin/cmd/script/transaction.rs +++ b/crates/forge/bin/cmd/script/transaction.rs @@ -5,7 +5,10 @@ use alloy_primitives::{Address, B256}; use ethers_core::types::{transaction::eip2718::TypedTransaction, NameOrAddress}; use eyre::{ContextCompat, Result, WrapErr}; use foundry_common::{fmt::format_token_raw, provider::ethers::RpcUrl, SELECTOR_LEN}; -use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, traces::CallTraceDecoder, utils::CallKind}; +use foundry_evm::{ + constants::DEFAULT_CREATE2_DEPLOYER, + traces::{CallKind, CallTraceDecoder}, +}; use foundry_utils::types::{ToAlloy, ToEthers}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index 1ad5488701ac..f25181c08b2f 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -42,6 +42,7 @@ mod summary; use summary::TestSummaryReporter; pub use filter::FilterArgs; +use forge::traces::render_trace_arena; // Loads project's figment and merges the build cli arguments into it foundry_config::merge_impl_figment_convert!(TestArgs, opts, evm_opts); @@ -236,6 +237,8 @@ impl TestArgs { if should_debug { let tests = outcome.clone().into_tests(); + // todo(onbjerg): why do we bother decoding everything and having multiple decoders if + // we are only going to use the first one? (see `DebuggerArgs` below) let mut decoders = Vec::new(); for test in tests { let mut result = test.result; @@ -264,28 +267,6 @@ impl TestArgs { for (kind, trace) in &mut result.traces { decoder.identify(trace, &mut local_identifier); decoder.identify(trace, &mut etherscan_identifier); - - let should_include = match kind { - // At verbosity level 3, we only display traces for failed tests - // At verbosity level 4, we also display the setup trace for failed - // tests At verbosity level 5, we display - // all traces for all tests - TraceKind::Setup => { - (verbosity >= 5) || - (verbosity == 4 && result.status == TestStatus::Failure) - } - TraceKind::Execution => { - verbosity > 3 || - (verbosity == 3 && result.status == TestStatus::Failure) - } - _ => false, - }; - - // We decode the trace if we either need to build a gas report or we need - // to print it - if should_include || self.gas_report { - decoder.decode(trace).await; - } } } @@ -702,7 +683,7 @@ async fn test( // Decode the traces let mut decoded_traces = Vec::with_capacity(result.traces.len()); - for (kind, trace) in &mut result.traces { + for (kind, trace) in &result.traces { decoder.identify(trace, &mut local_identifier); decoder.identify(trace, &mut etherscan_identifier); @@ -721,13 +702,8 @@ async fn test( TraceKind::Deployment => false, }; - // Decode the trace if we either need to build a gas report or we need to print it - if should_include || gas_reporting { - decoder.decode(trace).await; - } - if should_include { - decoded_traces.push(trace.to_string()); + decoded_traces.push(render_trace_arena(trace, &decoder).await?); } } diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index 43dfa39a347a..352012b58c11 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -1,7 +1,7 @@ use crate::{ constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS}, hashbrown::HashSet, - traces::{CallTraceArena, TraceCallData, TraceKind}, + traces::{CallTraceArena, TraceKind}, }; use alloy_primitives::U256; use comfy_table::{presets::ASCII_MARKDOWN, *}; @@ -51,6 +51,8 @@ impl GasReport { } fn analyze_node(&mut self, node_index: usize, arena: &CallTraceArena) { + // todo + /* let node = &arena.arena[node_index]; let trace = &node.trace; @@ -105,6 +107,7 @@ impl GasReport { node.children.iter().for_each(|index| { self.analyze_node(*index, arena); }); + */ } /// Finalizes the gas report by calculating the min, max, mean, and median for each function. diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index 9cd84f7c760a..16f42eb012d9 100644 --- a/crates/forge/src/result.rs +++ b/crates/forge/src/result.rs @@ -119,6 +119,7 @@ pub struct TestResult { pub kind: TestKind, /// Traces + #[serde(skip)] pub traces: Traces, /// Raw coverage info From f2332fed7e413b63cc6359b780c9d729dfbd1da9 Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 11 Dec 2023 15:29:22 +0100 Subject: [PATCH 03/13] wip --- Cargo.lock | 2 - crates/anvil/core/src/eth/transaction/mod.rs | 2 +- crates/anvil/src/eth/backend/executor.rs | 2 +- crates/anvil/src/eth/backend/mem/storage.rs | 3 +- crates/anvil/src/eth/otterscan/api.rs | 1 - crates/chisel/src/dispatcher.rs | 2 +- crates/evm/traces/Cargo.toml | 3 - crates/evm/traces/src/decoder/mod.rs | 40 ++++----- crates/evm/traces/src/lib.rs | 90 +++++++++++--------- crates/forge/bin/cmd/script/executor.rs | 3 +- crates/forge/bin/cmd/script/mod.rs | 1 - crates/forge/bin/cmd/script/runner.rs | 4 +- crates/forge/bin/cmd/test/mod.rs | 4 +- crates/forge/src/gas_report.rs | 64 ++++++-------- 14 files changed, 109 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 958cd98e00c4..386a6cb43b72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3324,7 +3324,6 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "const-hex", - "ethers-core", "eyre", "foundry-block-explorers", "foundry-common", @@ -3338,7 +3337,6 @@ dependencies = [ "once_cell", "ordered-float", "reth-revm-inspectors", - "revm", "serde", "tempfile", "tokio", diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index a483c0dbe1d7..9fee4e9e511d 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -14,7 +14,7 @@ use ethers_core::{ rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}, }, }; -use foundry_evm::traces::{CallTraceArena, CallTraceNode}; +use foundry_evm::traces::CallTraceNode; use foundry_utils::types::ToAlloy; use revm::{ interpreter::InstructionResult, diff --git a/crates/anvil/src/eth/backend/executor.rs b/crates/anvil/src/eth/backend/executor.rs index a1b16c5a16f0..7cfd05ee5c17 100644 --- a/crates/anvil/src/eth/backend/executor.rs +++ b/crates/anvil/src/eth/backend/executor.rs @@ -25,7 +25,7 @@ use foundry_evm::{ interpreter::InstructionResult, primitives::{BlockEnv, CfgEnv, EVMError, Env, ExecutionResult, Output, SpecId}, }, - traces::{CallTraceArena, CallTraceNode}, + traces::CallTraceNode, utils::{eval_to_instruction_result, halt_to_instruction_result}, }; use foundry_utils::types::{ToAlloy, ToEthers}; diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index 810c905ca519..ff9db85483cf 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -13,9 +13,8 @@ use anvil_core::eth::{ receipt::TypedReceipt, transaction::{MaybeImpersonatedTransaction, TransactionInfo}, }; -use ethers::{prelude::Trace, types::ActionType}; use foundry_evm::{ - revm::{interpreter::InstructionResult, primitives::Env}, + revm::primitives::Env, traces::{GethTraceBuilder, ParityTraceBuilder, TracingInspectorConfig}, }; use foundry_utils::types::{ToAlloy, ToEthers}; diff --git a/crates/anvil/src/eth/otterscan/api.rs b/crates/anvil/src/eth/otterscan/api.rs index a138ae8bc59c..b0cf7cd7e4b9 100644 --- a/crates/anvil/src/eth/otterscan/api.rs +++ b/crates/anvil/src/eth/otterscan/api.rs @@ -9,7 +9,6 @@ use crate::eth::{ }; use alloy_primitives::{Address, Bytes, B256, U256, U64}; use alloy_rpc_types::{Block, BlockId, BlockNumberOrTag as BlockNumber, Transaction}; -use foundry_utils::types::ToAlloy; use itertools::Itertools; use reth_rpc_types::trace::parity::{ Action, CallAction, CreateAction, CreateOutput, RewardAction, TraceOutput, diff --git a/crates/chisel/src/dispatcher.rs b/crates/chisel/src/dispatcher.rs index 251f964e5d0e..53acb553af1d 100644 --- a/crates/chisel/src/dispatcher.rs +++ b/crates/chisel/src/dispatcher.rs @@ -15,7 +15,7 @@ use foundry_evm::{ decode::decode_console_logs, traces::{ identifier::{EtherscanIdentifier, SignaturesIdentifier}, - render_trace, render_trace_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, + render_trace_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, }, }; use once_cell::sync::Lazy; diff --git a/crates/evm/traces/Cargo.toml b/crates/evm/traces/Cargo.toml index 9a8d747eb3d0..f650ddfd4f30 100644 --- a/crates/evm/traces/Cargo.toml +++ b/crates/evm/traces/Cargo.toml @@ -22,11 +22,8 @@ alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] } alloy-json-abi.workspace = true alloy-primitives = { workspace = true, features = ["serde", "getrandom", "arbitrary", "rlp"] } alloy-sol-types.workspace = true -revm.workspace = true reth-revm-inspectors = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/trace-builder" } -ethers-core.workspace = true - eyre = "0.6" futures = "0.3" hashbrown = "0.14" diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 9d94f8bcd1fd..75ac54295652 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -1,6 +1,6 @@ use crate::{ identifier::{AddressIdentity, SingleSignaturesIdentifier, TraceIdentifier}, - utils, CallTrace, CallTraceArena, DecodedCallData, DecodedCallTrace, + utils, CallTrace, CallTraceArena, DecodedCallData, DecodedCallLog, DecodedCallTrace, }; use alloy_dyn_abi::{DecodedEvent, DynSolValue, EventExt, FunctionExt, JsonAbiExt}; use alloy_json_abi::{Event, Function, JsonAbi as Abi}; @@ -234,25 +234,26 @@ impl CallTraceDecoder { // todo: avoid decoding creates // Decode precompile if let Some((label, func)) = precompiles::decode(&trace, 1) { - return DecodedCallTrace { label: Some(label), return_data: None, func: Some(func) } + return DecodedCallTrace { + label: Some(label), + return_data: None, + contract: None, + func: Some(func), + } } // Set label let label = self.labels.get(&trace.address).cloned(); // Set contract name - // todo - /*if trace.contract.is_none() { - if let Some(contract) = self.contracts.get(&trace.address) { - trace.contract = Some(contract.clone()); - } - }*/ + let contract = self.contracts.get(&trace.address).cloned(); let cdata = &trace.data; if trace.address == DEFAULT_CREATE2_DEPLOYER { return DecodedCallTrace { label, return_data: None, + contract, func: Some(DecodedCallData { signature: "create2".to_string(), args: vec![] }), }; } @@ -274,13 +275,14 @@ impl CallTraceDecoder { } }; let [func, ..] = &functions[..] else { - return DecodedCallTrace { label, return_data: None, func: None } + return DecodedCallTrace { label, return_data: None, contract, func: None } }; DecodedCallTrace { label, func: Some(self.decode_function_input(&trace, func)), return_data: self.decode_function_output(&trace, functions), + contract, } } else { let has_receive = self.receive_contracts.contains(&trace.address); @@ -299,6 +301,7 @@ impl CallTraceDecoder { } else { None }, + contract, func: Some(DecodedCallData { signature, args }), } } @@ -435,26 +438,25 @@ impl CallTraceDecoder { } /// Decodes an event. - async fn decode_event(&self, log: &Log) { - /*let TraceLog::Raw(raw_log) = log else { return }; - let &[t0, ..] = raw_log.topics() else { return }; + pub async fn decode_event<'a>(&self, log: &'a Log) -> DecodedCallLog<'a> { + let &[t0, ..] = log.topics() else { return DecodedCallLog::Raw(log) }; let mut events = Vec::new(); - let events = match self.events.get(&(t0, raw_log.topics().len() - 1)) { + let events = match self.events.get(&(t0, log.topics().len() - 1)) { Some(es) => es, None => { if let Some(identifier) = &self.signature_identifier { if let Some(event) = identifier.write().await.identify_event(&t0[..]).await { - events.push(get_indexed_event(event, raw_log)); + events.push(get_indexed_event(event, log)); } } &events } }; for event in events { - if let Ok(decoded) = event.decode_log(raw_log, false) { + if let Ok(decoded) = event.decode_log(log, false) { let params = reconstruct_params(event, &decoded); - *log = TraceLog::Decoded( + return DecodedCallLog::Decoded( event.name.clone(), params .into_iter() @@ -466,10 +468,10 @@ impl CallTraceDecoder { }) .collect(), ); - break } - }*/ - // todo + } + + DecodedCallLog::Raw(log) } fn apply_label(&self, value: &DynSolValue) -> String { diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 449e594683c3..99398fd9b249 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -7,7 +7,7 @@ #[macro_use] extern crate tracing; -use alloy_primitives::U256; +use alloy_primitives::{Log, U256}; use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact}; use foundry_evm_core::constants::CHEATCODE_ADDRESS; use futures::{future::BoxFuture, FutureExt}; @@ -46,6 +46,17 @@ pub struct DecodedCallTrace { pub label: Option, pub return_data: Option, pub func: Option, + pub contract: Option, +} + +pub enum DecodedCallLog<'a> { + /// A raw log. + Raw(&'a Log), + /// A decoded log. + /// + /// The first member of the tuple is the event name, and the second is a vector of decoded + /// parameters. + Decoded(String, Vec<(String, String)>), } const PIPE: &str = " │ "; @@ -74,7 +85,7 @@ pub async fn render_trace_arena( // Display trace header let (trace, return_data) = render_trace(&node.trace, decoder).await?; - writeln!(s, "{}", trace)?; + writeln!(s, "{left}{}", trace)?; // Display logs and subcalls let left_prefix = format!("{child}{BRANCH}"); @@ -82,18 +93,17 @@ pub async fn render_trace_arena( for child in &node.ordering { match child { LogCallOrder::Log(index) => { - /*let log = node.logs[*index].to_string(); + let log = render_trace_log(&node.logs[*index], decoder).await?; + // Prepend our tree structure symbols to each line of the displayed log log.lines().enumerate().try_for_each(|(i, line)| { - // todo: render log/decode log writeln!( s, "{}{}", if i == 0 { &left_prefix } else { &right_prefix }, line ) - })?;*/ - // todo + })?; } LogCallOrder::Call(index) => { inner( @@ -199,6 +209,41 @@ pub async fn render_trace( Ok((s, decoded.return_data)) } +/// Render a trace log. +async fn render_trace_log( + log: &Log, + decoder: &CallTraceDecoder, +) -> Result { + let mut s = String::new(); + let decoded = decoder.decode_event(log).await; + + match decoded { + DecodedCallLog::Raw(log) => { + for (i, topic) in log.topics().iter().enumerate() { + writeln!( + s, + "{:>13}: {}", + if i == 0 { "emit topic 0".to_string() } else { format!("topic {i}") }, + Paint::cyan(format!("{topic:?}")) + )?; + } + + write!(s, " data: {}", Paint::cyan(hex::encode_prefixed(&log.data)))?; + } + DecodedCallLog::Decoded(name, params) => { + let params = params + .iter() + .map(|(name, value)| format!("{name}: {value}")) + .collect::>() + .join(", "); + + write!(s, "emit {}({params})", Paint::cyan(name.clone()))?; + } + } + + Ok(s) +} + /// Specifies the kind of trace. #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)] pub enum TraceKind { @@ -267,36 +312,3 @@ pub fn load_contracts( }) .collect() } - -/// creates the memory data in 32byte chunks -/// see -fn convert_memory(data: &[u8]) -> Vec { - let mut memory = Vec::with_capacity((data.len() + 31) / 32); - for idx in (0..data.len()).step_by(32) { - let len = std::cmp::min(idx + 32, data.len()); - memory.push(hex::encode(&data[idx..len])); - } - memory -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn can_convert_memory() { - let mut data = vec![0u8; 32]; - assert_eq!( - convert_memory(&data), - vec!["0000000000000000000000000000000000000000000000000000000000000000".to_string()] - ); - data.extend(data.clone()); - assert_eq!( - convert_memory(&data), - vec![ - "0000000000000000000000000000000000000000000000000000000000000000".to_string(), - "0000000000000000000000000000000000000000000000000000000000000000".to_string() - ] - ); - } -} diff --git a/crates/forge/bin/cmd/script/executor.rs b/crates/forge/bin/cmd/script/executor.rs index dc2a7fb1983e..a35be3e12899 100644 --- a/crates/forge/bin/cmd/script/executor.rs +++ b/crates/forge/bin/cmd/script/executor.rs @@ -12,7 +12,6 @@ use forge::{ executors::ExecutorBuilder, inspectors::{cheatcodes::BroadcastableTransactions, CheatsConfig}, traces::{CallTraceDecoder, Traces}, - utils::CallKind, }; use foundry_cli::utils::{ensure_clean_constructor, needs_setup}; use foundry_common::{provider::ethers::RpcUrl, shell}; @@ -219,7 +218,7 @@ impl ScriptArgs { // type hint let res: Result = res; - let (tx, mut traces) = res?; + let (tx, traces) = res?; // Transaction will be `None`, if execution didn't pass. if tx.is_none() || script_config.evm_opts.verbosity > 3 { diff --git a/crates/forge/bin/cmd/script/mod.rs b/crates/forge/bin/cmd/script/mod.rs index bb85ea429907..adcd0e858869 100644 --- a/crates/forge/bin/cmd/script/mod.rs +++ b/crates/forge/bin/cmd/script/mod.rs @@ -20,7 +20,6 @@ use forge::{ identifier::{EtherscanIdentifier, LocalTraceIdentifier, SignaturesIdentifier}, render_trace_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, Traces, }, - utils::CallKind, }; use foundry_cli::opts::MultiWallet; use foundry_common::{ diff --git a/crates/forge/bin/cmd/script/runner.rs b/crates/forge/bin/cmd/script/runner.rs index 7814e0004b5e..c6e1f689ad1e 100644 --- a/crates/forge/bin/cmd/script/runner.rs +++ b/crates/forge/bin/cmd/script/runner.rs @@ -239,7 +239,7 @@ impl ScriptRunner { gas_used, logs, traces: traces - .map(|mut traces| { + .map(|traces| { // Manually adjust gas for the trace to add back the stipend/real used gas // todo(onbjerg): not possible //traces.arena[0].trace.gas_cost = gas_used; @@ -301,7 +301,7 @@ impl ScriptRunner { gas_used, logs, traces: traces - .map(|mut traces| { + .map(|traces| { // Manually adjust gas for the trace to add back the stipend/real used gas // todo(onbjerg): not possible //traces.arena[0].trace.gas_cost = gas_used; diff --git a/crates/forge/bin/cmd/test/mod.rs b/crates/forge/bin/cmd/test/mod.rs index f25181c08b2f..9e2bbf943c0b 100644 --- a/crates/forge/bin/cmd/test/mod.rs +++ b/crates/forge/bin/cmd/test/mod.rs @@ -264,7 +264,7 @@ impl TestArgs { EtherscanIdentifier::new(&config, remote_chain_id)?; // Decode the traces - for (kind, trace) in &mut result.traces { + for (_, trace) in &mut result.traces { decoder.identify(trace, &mut local_identifier); decoder.identify(trace, &mut etherscan_identifier); } @@ -713,7 +713,7 @@ async fn test( } if gas_reporting { - gas_report.analyze(&result.traces); + gas_report.analyze(&result.traces, &decoder).await; } } let block_outcome = diff --git a/crates/forge/src/gas_report.rs b/crates/forge/src/gas_report.rs index 352012b58c11..497d0078064f 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -1,7 +1,7 @@ use crate::{ constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS}, hashbrown::HashSet, - traces::{CallTraceArena, TraceKind}, + traces::{CallTraceArena, CallTraceDecoder, CallTraceNode, DecodedCallData, TraceKind}, }; use alloy_primitives::U256; use comfy_table::{presets::ASCII_MARKDOWN, *}; @@ -44,23 +44,25 @@ impl GasReport { } /// Analyzes the given traces and generates a gas report. - pub fn analyze(&mut self, traces: &[(TraceKind, CallTraceArena)]) { - traces.iter().for_each(|(_, trace)| { - self.analyze_node(0, trace); - }); + pub async fn analyze( + &mut self, + traces: &[(TraceKind, CallTraceArena)], + decoder: &CallTraceDecoder, + ) { + for node in traces.iter().flat_map(|(_, arena)| arena.nodes()) { + self.analyze_node(node, decoder).await; + } } - fn analyze_node(&mut self, node_index: usize, arena: &CallTraceArena) { - // todo - /* - let node = &arena.arena[node_index]; + async fn analyze_node(&mut self, node: &CallTraceNode, decoder: &CallTraceDecoder) { let trace = &node.trace; + let decoded = decoder.decode_function(&node.trace).await; if trace.address == CHEATCODE_ADDRESS || trace.address == HARDHAT_CONSOLE_ADDRESS { return } - if let Some(name) = &trace.contract { + if let Some(name) = &decoded.contract { let contract_name = name.rsplit(':').next().unwrap_or(name.as_str()); // If the user listed the contract in 'gas_reports' (the foundry.toml field) a // report for the contract is generated even if it's listed in the ignore @@ -78,36 +80,26 @@ impl GasReport { if self.should_report(contract_name) { let contract_info = self.contracts.entry(name.to_string()).or_default(); - match &trace.data { - TraceCallData::Raw(bytes) => { - if trace.created() { - contract_info.gas = U256::from(trace.gas_cost); - contract_info.size = U256::from(bytes.len()); - } - } - TraceCallData::Decoded { signature, .. } => { - let name = signature.split('(').next().unwrap(); - // ignore any test/setup functions - let should_include = - !(name.is_test() || name.is_invariant_test() || name.is_setup()); - if should_include { - let gas_info = contract_info - .functions - .entry(name.into()) - .or_default() - .entry(signature.clone()) - .or_default(); - gas_info.calls.push(U256::from(trace.gas_cost)); - } + if trace.kind.is_any_create() { + contract_info.gas = U256::from(trace.gas_used); + contract_info.size = U256::from(trace.data.len()); + } else if let Some(DecodedCallData { signature, .. }) = decoded.func { + let name = signature.split('(').next().unwrap(); + // ignore any test/setup functions + let should_include = + !(name.is_test() || name.is_invariant_test() || name.is_setup()); + if should_include { + let gas_info = contract_info + .functions + .entry(name.to_string()) + .or_default() + .entry(signature.clone()) + .or_default(); + gas_info.calls.push(U256::from(trace.gas_used)); } } } } - - node.children.iter().for_each(|index| { - self.analyze_node(*index, arena); - }); - */ } /// Finalizes the gas report by calculating the min, max, mean, and median for each function. From f31039c8f76bfd3bdeee0eaecfdae9cd8a4baebe Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 11 Dec 2023 11:26:37 -0400 Subject: [PATCH 04/13] chore: fix deps --- Cargo.lock | 429 +++++++++++++++++------------------ Cargo.toml | 2 +- crates/anvil/Cargo.toml | 2 +- crates/anvil/core/Cargo.toml | 2 +- crates/evm/traces/Cargo.toml | 2 +- 5 files changed, 210 insertions(+), 227 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 267a12120245..a08d64154ac2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,9 +78,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "alloy-chains" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e9249bbabebe77f78e6a8f1984f9cd6151bb3297e484bb073cfae7a6dbd9f22" +checksum = "e7f12f8177eddf9275fa9ae5fd73b50cee062f9b1eb95ef435f28354c79ba386" dependencies = [ "num_enum 0.7.1", "serde", @@ -220,7 +220,7 @@ checksum = "c0391754c09fab4eae3404d19d0d297aa1c670c1775ab51d8a5312afeca23157" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -270,7 +270,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.39", + "syn 2.0.40", "syn-solidity", "tiny-keccak", ] @@ -395,9 +395,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" +checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" dependencies = [ "anstyle", "anstyle-parse", @@ -415,30 +415,30 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" +checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -755,7 +755,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -772,7 +772,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -795,15 +795,6 @@ dependencies = [ "bytemuck", ] -[[package]] -name = "atomic-polyfill" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" -dependencies = [ - "critical-section", -] - [[package]] name = "atomic-take" version = "1.1.0" @@ -975,7 +966,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.39", + "syn 2.0.40", "which", ] @@ -1156,7 +1147,7 @@ checksum = "f3e5afa991908cfbe79bd3109b824e473a1dc5f74f31fab91bb44c9e245daa77" dependencies = [ "boa_gc", "boa_macros", - "hashbrown 0.14.2", + "hashbrown 0.14.3", "indexmap 2.1.0", "once_cell", "phf 0.11.2", @@ -1172,7 +1163,7 @@ checksum = "005fa0c5bd20805466dda55eb34cd709bb31a2592bb26927b47714eeed6914d8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "synstructure 0.13.0", ] @@ -1530,9 +1521,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.10" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fffed7514f420abec6d183b1d3acfd9099c79c3a10a06ade4f8203f1411272" +checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" dependencies = [ "clap_builder", "clap_derive", @@ -1540,9 +1531,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.9" +version = "4.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63361bae7eef3771745f02d8d892bec2fee5f6e34af316ba556e7f97a7069ff1" +checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" dependencies = [ "anstream", "anstyle", @@ -1581,7 +1572,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -1674,9 +1665,9 @@ dependencies = [ [[package]] name = "coins-ledger" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12adb2f4914ec6d8659cd9d1630463ca13ac90f5be18133cb9a70921f15fc145" +checksum = "9b913b49d2e008b23cffb802f29b8051feddf7b2cc37336ab9a7a410f832395a" dependencies = [ "async-trait", "byteorder", @@ -1685,13 +1676,9 @@ dependencies = [ "hex", "hidapi-rusb", "js-sys", - "lazy_static", - "libc", "log", - "matches", "nix 0.26.4", - "serde", - "tap", + "once_cell", "thiserror", "tokio", "tracing", @@ -1811,9 +1798,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -1821,9 +1808,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" @@ -2057,7 +2044,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2068,7 +2055,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2102,9 +2089,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" dependencies = [ "powerfmt", "serde", @@ -2129,7 +2116,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2253,7 +2240,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2387,7 +2374,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2585,7 +2572,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.39", + "syn 2.0.40", "toml 0.8.8", "walkdir", ] @@ -2602,7 +2589,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2627,7 +2614,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.39", + "syn 2.0.40", "tempfile", "thiserror", "tiny-keccak", @@ -2817,19 +2804,25 @@ dependencies = [ [[package]] name = "eyre" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" +checksum = "8bbb8258be8305fb0237d7b295f47bb24ff1b136a535f473baf40e70468515aa" dependencies = [ "indenter", "once_cell", ] +[[package]] +name = "fast-float" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c" + [[package]] name = "faster-hex" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239f7bfb930f820ab16a9cd95afc26f88264cf6905c960b340a615384aa3338a" +checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" dependencies = [ "serde", ] @@ -2861,7 +2854,7 @@ dependencies = [ "bytes", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2877,13 +2870,13 @@ dependencies = [ [[package]] name = "fd-lock" -version = "4.0.0" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0377f1edc77dbd1118507bc7a66e4ab64d2b90c66f90726dc801e73a8c68f9" +checksum = "b93f7a0db71c99f68398f80653ed05afb0b00e062e1a20c7ff849c4edfabbbcc" dependencies = [ "cfg-if", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2924,14 +2917,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "redox_syscall", + "windows-sys 0.52.0", ] [[package]] @@ -3105,9 +3098,9 @@ dependencies = [ [[package]] name = "foundry-block-explorers" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47331ff0955a60df66db753f5dcfe3ca0275abe192e58c9eb6d0d8c1a131e604" +checksum = "43408b384e5888fed99a5f25f86cef7e19dca10c750e948cbeb219f59847712f" dependencies = [ "alloy-chains", "alloy-json-abi", @@ -3475,7 +3468,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3486,7 +3479,7 @@ dependencies = [ "ethers-core", "ethers-providers", "eyre", - "fd-lock 4.0.0", + "fd-lock 4.0.1", "foundry-common", "foundry-compilers", "foundry-config", @@ -3617,7 +3610,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3725,9 +3718,9 @@ dependencies = [ [[package]] name = "gix-actor" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "948a5f9e43559d16faf583694f1c742eb401ce24ce8e6f2238caedea7486433c" +checksum = "2eadca029ef716b4378f7afb19f7ee101fde9e58ba1f1445971315ac866db417" dependencies = [ "bstr", "btoi", @@ -3760,9 +3753,9 @@ dependencies = [ [[package]] name = "gix-config-value" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea7505b97f4d8e7933e29735a568ba2f86d8de466669d9f0e8321384f9972f47" +checksum = "6419db582ea84dfb58c7e7b0af7fd62c808aa14954af2936a33f89b0f4ed018e" dependencies = [ "bitflags 2.4.1", "bstr", @@ -3773,9 +3766,9 @@ dependencies = [ [[package]] name = "gix-date" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7df669639582dc7c02737642f76890b03b5544e141caba68a7d6b4eb551e0d" +checksum = "468dfbe411f335f01525a1352271727f8e7772075a93fa747260f502086b30be" dependencies = [ "bstr", "itoa", @@ -3785,9 +3778,9 @@ dependencies = [ [[package]] name = "gix-features" -version = "0.36.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f4365ba17c4f218d7fd9ec102b8d2d3cb0ca200a835e81151ace7778aec827" +checksum = "4d46a4a5c6bb5bebec9c0d18b65ada20e6517dbd7cf855b87dd4bbdce3a771b2" dependencies = [ "gix-hash", "gix-trace", @@ -3799,18 +3792,18 @@ dependencies = [ [[package]] name = "gix-fs" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd171c0cae97cd0dc57e7b4601cb1ebf596450e263ef3c02be9107272c877bd" +checksum = "20e86eb040f5776a5ade092282e51cdcad398adb77d948b88d17583c2ae4e107" dependencies = [ "gix-features", ] [[package]] name = "gix-glob" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fac08925dbc14d414bd02eb45ffb4cecd912d1fce3883f867bd0103c192d3e4" +checksum = "5db19298c5eeea2961e5b3bf190767a2d1f09b8802aeb5f258e42276350aff19" dependencies = [ "bitflags 2.4.1", "bstr", @@ -3820,9 +3813,9 @@ dependencies = [ [[package]] name = "gix-hash" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1884c7b41ea0875217c1be9ce91322f90bde433e91d374d0e1276073a51ccc60" +checksum = "1f8cf8c2266f63e582b7eb206799b63aa5fa68ee510ad349f637dfe2d0653de0" dependencies = [ "faster-hex", "thiserror", @@ -3830,9 +3823,9 @@ dependencies = [ [[package]] name = "gix-lock" -version = "11.0.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4feb1dcd304fe384ddc22edba9dd56a42b0800032de6537728cea2f033a4f37" +checksum = "7e5c65e6a29830a435664891ced3f3c1af010f14900226019590ee0971a22f37" dependencies = [ "gix-tempfile", "gix-utils", @@ -3860,9 +3853,9 @@ dependencies = [ [[package]] name = "gix-path" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1d370115171e3ae03c5c6d4f7d096f2981a40ddccb98dfd704c773530ba73b" +checksum = "d86d6fac2fabe07b67b7835f46d07571f68b11aa1aaecae94fe722ea4ef305e1" dependencies = [ "bstr", "gix-trace", @@ -3887,8 +3880,6 @@ dependencies = [ "gix-path", "gix-tempfile", "gix-validate", - "memmap2 0.5.10", - "nom", "memmap2 0.7.1", "thiserror", "winnow", @@ -3896,9 +3887,9 @@ dependencies = [ [[package]] name = "gix-sec" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b9542ac025a8c02ed5d17b3fc031a111a384e859d0be3532ec4d58c40a0f28" +checksum = "a36ea2c5907d64a9b4b5d3cc9f430e6c30f0509646b5e38eb275ca57c5bf29e2" dependencies = [ "bitflags 2.4.1", "gix-path", @@ -3908,9 +3899,9 @@ dependencies = [ [[package]] name = "gix-tempfile" -version = "11.0.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cc2205cf10d99f70b96e04e16c55d4c7cf33efc151df1f793e29fd12a931f8" +checksum = "388dd29114a86ec69b28d1e26d6d63a662300ecf61ab3f4cc578f7d7dc9e7e23" dependencies = [ "gix-fs", "libc", @@ -3921,24 +3912,24 @@ dependencies = [ [[package]] name = "gix-trace" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b6d623a1152c3facb79067d6e2ecdae48130030cf27d6eb21109f13bd7b836" +checksum = "b686a35799b53a9825575ca3f06481d0a053a409c4d97ffcf5ddd67a8760b497" [[package]] name = "gix-utils" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b85d89dc728613e26e0ed952a19583744e7f5240fcd4aa30d6c824ffd8b52f0f" +checksum = "9f82c41937f00e15a1f6cb0b55307f0ca1f77f4407ff2bf440be35aa688c6a3e" dependencies = [ "fastrand", ] [[package]] name = "gix-validate" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05cab2b03a45b866156e052aa38619f4ece4adcb2f79978bfc249bc3b21b8c5" +checksum = "75b7d8e4274be69f284bbc7e6bb2ccf7065dbcdeba22d8c549f2451ae426883f" dependencies = [ "bstr", "thiserror", @@ -4049,6 +4040,15 @@ dependencies = [ "ahash 0.7.7", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.6", +] + [[package]] name = "hashbrown" version = "0.14.3" @@ -4163,9 +4163,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -4244,7 +4244,7 @@ dependencies = [ "futures-util", "http", "hyper", - "rustls 0.21.9", + "rustls 0.21.10", "tokio", "tokio-rustls 0.24.1", ] @@ -4653,9 +4653,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jobserver" @@ -4813,9 +4813,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libgit2-sys" @@ -4853,7 +4853,7 @@ checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ "bitflags 2.4.1", "libc", - "redox_syscall 0.4.1", + "redox_syscall", ] [[package]] @@ -4882,9 +4882,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "litemap" @@ -4952,12 +4952,6 @@ dependencies = [ "regex-automata 0.1.10", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "matchit" version = "0.7.3" @@ -4987,9 +4981,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.35" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3f88addd34930bc5f01b9dc19f780447e51c92bf2536e3ded058018271775d" +checksum = "80992cb0e05f22cc052c99f8e883f1593b891014b96a8b4637fd274d7030c85e" dependencies = [ "ammonia", "anyhow", @@ -5003,6 +4997,7 @@ dependencies = [ "memchr", "once_cell", "opener", + "pathdiff", "pulldown-cmark", "regex", "serde", @@ -5037,15 +5032,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memmap2" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375" -dependencies = [ - "libc", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -5095,7 +5081,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5131,9 +5117,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "log", @@ -5366,7 +5352,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5378,7 +5364,7 @@ dependencies = [ "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5407,12 +5393,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" dependencies = [ - "atomic-polyfill", "critical-section", + "portable-atomic", ] [[package]] @@ -5465,9 +5451,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.60" +version = "0.10.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" +checksum = "6b8419dc8cc6d866deb801274bba2e6f8f6108c1bb7fcc10ee5ab864931dbb45" dependencies = [ "bitflags 2.4.1", "cfg-if", @@ -5486,7 +5472,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5497,9 +5483,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.96" +version = "0.9.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" +checksum = "c3eaad34cdd97d81de97964fc7f29e2d104f483840d906ef56daa1912338460b" dependencies = [ "cc", "libc", @@ -5515,9 +5501,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "ordered-float" -version = "4.1.1" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536900a8093134cf9ccf00a27deb3532421099e958d9dd431135d0c7543ca1e8" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" dependencies = [ "num-traits", ] @@ -5623,7 +5609,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", "windows-targets 0.48.5", ] @@ -5651,6 +5637,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "pbkdf2" version = "0.11.0" @@ -5693,7 +5685,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5748,7 +5740,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5851,7 +5843,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5889,7 +5881,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5967,9 +5959,9 @@ checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" [[package]] name = "portable-atomic" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" [[package]] name = "postcard" @@ -6017,7 +6009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" dependencies = [ "proc-macro2", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6094,7 +6086,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "version_check", "yansi 1.0.0-rc.1", ] @@ -6327,15 +6319,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.4.1" @@ -6455,7 +6438,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.21.9", + "rustls 0.21.10", "rustls-native-certs", "rustls-pemfile", "serde", @@ -6476,8 +6459,8 @@ dependencies = [ [[package]] name = "reth-revm-inspectors" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/trace-builder#64b2ce23cad2d3b68700ad5bc007b83e6a61e3ac" +version = "0.1.0-alpha.13" +source = "git+https://github.com/paradigmxyz/reth/?branch=main#fa1584b22306f6f0573a5d4c85f77a685c3e65d4" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -6493,8 +6476,8 @@ dependencies = [ [[package]] name = "reth-rpc-types" -version = "0.1.0-alpha.12" -source = "git+https://github.com/paradigmxyz/reth/?branch=onbjerg/trace-builder#64b2ce23cad2d3b68700ad5bc007b83e6a61e3ac" +version = "0.1.0-alpha.13" +source = "git+https://github.com/paradigmxyz/reth/?branch=main#fa1584b22306f6f0573a5d4c85f77a685c3e65d4" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -6590,9 +6573,9 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.6" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", "getrandom 0.2.11", @@ -6816,15 +6799,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -6841,12 +6824,12 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.6", + "ring 0.17.7", "rustls-webpki", "sct", ] @@ -6878,7 +6861,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.6", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -6925,9 +6908,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "ryu-js" @@ -7034,7 +7017,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.6", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -7068,7 +7051,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2acea373acb8c21ecb5a23741452acd2593ed44ee3d343e72baaa143bc89d0d5" dependencies = [ - "secp256k1-sys 0.9.0", + "secp256k1-sys 0.9.1", ] [[package]] @@ -7082,9 +7065,9 @@ dependencies = [ [[package]] name = "secp256k1-sys" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e67c467c38fd24bd5499dc9a18183b31575c12ee549197e3e20d57aa4fe3b7" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" dependencies = [ "cc", ] @@ -7168,7 +7151,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7222,7 +7205,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7272,7 +7255,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7297,7 +7280,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7600,7 +7583,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7668,9 +7651,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" dependencies = [ "proc-macro2", "quote", @@ -7686,7 +7669,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7715,7 +7698,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "unicode-xid", ] @@ -7754,7 +7737,7 @@ checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "redox_syscall", "rustix", "windows-sys 0.48.0", ] @@ -7815,9 +7798,9 @@ dependencies = [ [[package]] name = "thin-vec" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8" +checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" [[package]] name = "thiserror" @@ -7836,7 +7819,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7942,9 +7925,9 @@ checksum = "c7c4ceeeca15c8384bbc3e011dbd8fccb7f068a440b752b7d9b32ceb0ca0e2e8" [[package]] name = "tokio" -version = "1.34.0" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ "backtrace", "bytes", @@ -7967,7 +7950,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7997,7 +7980,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.9", + "rustls 0.21.10", "tokio", ] @@ -8021,7 +8004,7 @@ dependencies = [ "futures-util", "log", "native-tls", - "rustls 0.21.9", + "rustls 0.21.10", "tokio", "tokio-native-tls", "tokio-rustls 0.24.1", @@ -8188,7 +8171,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -8299,9 +8282,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" @@ -8317,7 +8300,7 @@ dependencies = [ "log", "native-tls", "rand 0.8.5", - "rustls 0.21.9", + "rustls 0.21.10", "sha1", "thiserror", "url", @@ -8375,9 +8358,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" [[package]] name = "unicode-bom" @@ -8449,15 +8432,15 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf16_iter" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52df8b7fb78e7910d776fccf2e42ceaf3604d55e8e7eb2dbd183cb1441d8a692" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" [[package]] name = "utf8_iter" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a8922555b9500e3d865caed19330172cd67cbf82203f1a3311d8c305cc9f33" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" @@ -8566,7 +8549,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "wasm-bindgen-shared", ] @@ -8600,7 +8583,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -8675,7 +8658,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" dependencies = [ - "ring 0.17.6", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -8946,9 +8929,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.19" +version = "0.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "b67b5f0a4e7a27a64c651977932b9dc5667ca7fc31ac44b03ed37a0cf42fdfff" dependencies = [ "memchr", ] @@ -9041,28 +9024,28 @@ checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "synstructure 0.13.0", ] [[package]] name = "zerocopy" -version = "0.7.26" +version = "0.7.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +checksum = "306dca4455518f1f31635ec308b6b3e4eb1b11758cefafc782827d0aa7acb5c7" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.26" +version = "0.7.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +checksum = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -9082,7 +9065,7 @@ checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "synstructure 0.13.0", ] @@ -9103,7 +9086,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -9126,7 +9109,7 @@ checksum = "7a4a1638a1934450809c2266a70362bfc96cd90550c073f5b8a55014d1010157" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 45179461e06a..01147f3731f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -220,4 +220,4 @@ alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy/", branch = "onbjerg revm = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze" } revm-primitives = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze" } revm-interpreter = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze" } -revm-precompile = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze" } +revm-precompile = { git = "https://github.com/bluealloy/revm", branch = "reth_freeze" } \ No newline at end of file diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index c99bd3c78665..ef46ca371306 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -39,7 +39,7 @@ alloy-primitives = { workspace = true, features = ["serde"] } alloy-rpc-types.workspace = true alloy-providers.workspace = true alloy-transport.workspace = true -reth-rpc-types = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/trace-builder" } +reth-rpc-types = { git = "https://github.com/paradigmxyz/reth/", branch = "main" } # axum related diff --git a/crates/anvil/core/Cargo.toml b/crates/anvil/core/Cargo.toml index aca25fca2529..8ddad4a71959 100644 --- a/crates/anvil/core/Cargo.toml +++ b/crates/anvil/core/Cargo.toml @@ -26,7 +26,7 @@ serde = { workspace = true, optional = true } serde_json.workspace = true bytes = { version = "1.4" } open-fastrlp = { version = "0.1.4", optional = true } -reth-rpc-types = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/trace-builder" } +reth-rpc-types = { git = "https://github.com/paradigmxyz/reth/", branch = "main" } # trie hash-db = { version = "0.15", default-features = false } diff --git a/crates/evm/traces/Cargo.toml b/crates/evm/traces/Cargo.toml index a5f286a4d715..d3fe2338e9b3 100644 --- a/crates/evm/traces/Cargo.toml +++ b/crates/evm/traces/Cargo.toml @@ -21,7 +21,7 @@ alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] } alloy-json-abi.workspace = true alloy-primitives = { workspace = true, features = ["serde", "getrandom", "arbitrary", "rlp"] } alloy-sol-types.workspace = true -reth-revm-inspectors = { git = "https://github.com/paradigmxyz/reth/", branch = "onbjerg/trace-builder" } +reth-revm-inspectors = { git = "https://github.com/paradigmxyz/reth/", branch = "main" } eyre = "0.6" futures = "0.3" From 0efdac9d79bd897929c952903c66ab3086bf4602 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 11 Dec 2023 11:29:29 -0400 Subject: [PATCH 05/13] remove utils import --- crates/evm/traces/src/decoder/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 62f1ee95b0de..e7335bc2f14e 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -1,6 +1,6 @@ use crate::{ identifier::{AddressIdentity, SingleSignaturesIdentifier, TraceIdentifier}, - utils, CallTrace, CallTraceArena, DecodedCallData, DecodedCallLog, DecodedCallTrace, + CallTrace, CallTraceArena, DecodedCallData, DecodedCallLog, DecodedCallTrace, }; use alloy_dyn_abi::{DecodedEvent, DynSolValue, EventExt, FunctionExt, JsonAbiExt}; use alloy_json_abi::{Event, Function, JsonAbi as Abi}; From e2d260af7c54dafcca83937b3c68e3b79174cdc9 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 11 Dec 2023 11:50:22 -0400 Subject: [PATCH 06/13] chore: remove errors --- crates/anvil/core/src/eth/transaction/mod.rs | 2 +- crates/anvil/src/eth/api.rs | 2 +- crates/anvil/src/eth/backend/executor.rs | 1 + crates/anvil/src/eth/backend/mem/storage.rs | 2 +- crates/anvil/tests/it/ipc.rs | 2 +- crates/doc/src/preprocessor/deployments.rs | 28 +++++++++++--------- crates/forge/bin/cmd/script/executor.rs | 2 +- crates/forge/bin/cmd/script/mod.rs | 1 - crates/forge/bin/cmd/script/transaction.rs | 8 ++++-- 9 files changed, 28 insertions(+), 20 deletions(-) diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index 84e3225a1c6e..ba89b1e6c00a 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -14,8 +14,8 @@ use ethers_core::{ rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream}, }, }; -use foundry_evm::traces::CallTraceNode; use foundry_common::types::ToAlloy; +use foundry_evm::traces::CallTraceNode; use revm::{ interpreter::InstructionResult, primitives::{CreateScheme, OptimismFields, TransactTo, TxEnv}, diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index 5fc963835ec8..2fe611330be5 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -70,8 +70,8 @@ use anvil_core::{ }; use anvil_rpc::{error::RpcError, response::ResponseResult}; use ethers::{types::transaction::eip712::TypedData, utils::rlp}; -use foundry_common::provider::alloy::ProviderBuilder; use foundry_common::{ + provider::alloy::ProviderBuilder, types::{ToAlloy, ToEthers}, }; use foundry_evm::{ diff --git a/crates/anvil/src/eth/backend/executor.rs b/crates/anvil/src/eth/backend/executor.rs index 0c21b82d370b..5f2069a5a8e9 100644 --- a/crates/anvil/src/eth/backend/executor.rs +++ b/crates/anvil/src/eth/backend/executor.rs @@ -328,6 +328,7 @@ impl<'a, 'b, DB: Db + ?Sized, Validator: TransactionValidator> Iterator .get_traces() .clone() .into_nodes(), + nonce, }; Some(TransactionExecutionOutcome::Executed(tx)) diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index ff9db85483cf..980f362bac08 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -13,11 +13,11 @@ use anvil_core::eth::{ receipt::TypedReceipt, transaction::{MaybeImpersonatedTransaction, TransactionInfo}, }; +use foundry_common::types::{ToAlloy, ToEthers}; use foundry_evm::{ revm::primitives::Env, traces::{GethTraceBuilder, ParityTraceBuilder, TracingInspectorConfig}, }; -use foundry_utils::types::{ToAlloy, ToEthers}; use parking_lot::RwLock; use reth_rpc_types::{ trace::{ diff --git a/crates/anvil/tests/it/ipc.rs b/crates/anvil/tests/it/ipc.rs index 7324389646ed..a933f8512c46 100644 --- a/crates/anvil/tests/it/ipc.rs +++ b/crates/anvil/tests/it/ipc.rs @@ -1,8 +1,8 @@ //! IPC tests +use alloy_primitives::U256; use alloy_providers::provider::TempProvider; use anvil::{spawn, NodeConfig}; -use alloy_primitives::U256; use ethers::{core::rand, prelude::Middleware}; use futures::StreamExt; diff --git a/crates/doc/src/preprocessor/deployments.rs b/crates/doc/src/preprocessor/deployments.rs index b081ed59a0d7..aaef8e42501f 100644 --- a/crates/doc/src/preprocessor/deployments.rs +++ b/crates/doc/src/preprocessor/deployments.rs @@ -1,7 +1,10 @@ use super::{Preprocessor, PreprocessorId}; use crate::{Document, PreprocessorOutput}; use alloy_primitives::Address; -use std::{fs, path::PathBuf}; +use std::{ + fs, + path::{Path, PathBuf}, +}; /// [Deployments] preprocessor id. pub const DEPLOYMENTS_ID: PreprocessorId = PreprocessorId("deployments"); @@ -33,20 +36,21 @@ impl Preprocessor for Deployments { fn preprocess(&self, documents: Vec) -> Result, eyre::Error> { let deployments_dir = - self.root.join(self.deployments.as_ref().unwrap_or(&PathBuf::from("deployments"))); + self.root.join(self.deployments.as_deref().unwrap_or(Path::new("deployments"))); // Gather all networks from the deployments directory. let networks = fs::read_dir(&deployments_dir)? - .map(|x| { - x.map(|y| { - if y.file_type()?.is_dir() { - Ok(y.file_name().into_string().map_err(|e| { - eyre::eyre!("Failed to extract directory name: {:?}", e) - })?) - } else { - eyre::bail!("Not a directory.") - } - })? + .map(|entry| { + let entry = entry?; + let path = entry.path(); + if entry.file_type()?.is_dir() { + entry + .file_name() + .into_string() + .map_err(|e| eyre::eyre!("failed to extract directory name: {e:?}")) + } else { + eyre::bail!("not a directory: {}", path.display()) + } }) .collect::, _>>()?; diff --git a/crates/forge/bin/cmd/script/executor.rs b/crates/forge/bin/cmd/script/executor.rs index 03dccfbc8c3f..70dbadaeb4e8 100644 --- a/crates/forge/bin/cmd/script/executor.rs +++ b/crates/forge/bin/cmd/script/executor.rs @@ -174,7 +174,7 @@ impl ScriptArgs { return Some(AdditionalContract { opcode: node.trace.kind, address: node.trace.address, - init_code: node.trace.data.to_vec(), + init_code: node.trace.data.clone(), }); } None diff --git a/crates/forge/bin/cmd/script/mod.rs b/crates/forge/bin/cmd/script/mod.rs index 3c321519dc19..c4df4f40f7e9 100644 --- a/crates/forge/bin/cmd/script/mod.rs +++ b/crates/forge/bin/cmd/script/mod.rs @@ -678,7 +678,6 @@ impl ScriptConfig { /// If not, warns the user. async fn check_shanghai_support(&self) -> Result<()> { let chain_ids = self.total_rpcs.iter().map(|rpc| async move { - let provider = ethers_providers::Provider::::try_from(rpc).ok()?; let id = provider.get_chainid().await.ok()?; let id_u64: u64 = id.try_into().ok()?; diff --git a/crates/forge/bin/cmd/script/transaction.rs b/crates/forge/bin/cmd/script/transaction.rs index 59244c9f1b1e..eb8010a60e68 100644 --- a/crates/forge/bin/cmd/script/transaction.rs +++ b/crates/forge/bin/cmd/script/transaction.rs @@ -4,12 +4,16 @@ use alloy_json_abi::Function; use alloy_primitives::{Address, Bytes, B256}; use ethers_core::types::{transaction::eip2718::TypedTransaction, NameOrAddress}; use eyre::{ContextCompat, Result, WrapErr}; -use foundry_common::{fmt::format_token_raw, provider::ethers::RpcUrl, SELECTOR_LEN}; +use foundry_common::{ + fmt::format_token_raw, + provider::ethers::RpcUrl, + types::{ToAlloy, ToEthers}, + SELECTOR_LEN, +}; use foundry_evm::{ constants::DEFAULT_CREATE2_DEPLOYER, traces::{CallKind, CallTraceDecoder}, }; -use foundry_utils::types::{ToAlloy, ToEthers}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; From 503075c6461b148fdb0158570c2ff519a678c6d5 Mon Sep 17 00:00:00 2001 From: Enrique Ortiz Date: Mon, 11 Dec 2023 12:00:40 -0400 Subject: [PATCH 07/13] chore: use render_trace_arena --- crates/forge/tests/it/config.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/forge/tests/it/config.rs b/crates/forge/tests/it/config.rs index 1ab7f0e31882..77af8d450a95 100644 --- a/crates/forge/tests/it/config.rs +++ b/crates/forge/tests/it/config.rs @@ -10,9 +10,13 @@ use foundry_config::{ InvariantConfig, RpcEndpoint, RpcEndpoints, }; use foundry_evm::{ - decode::decode_console_logs, inspectors::CheatsConfig, revm::primitives::SpecId, + decode::decode_console_logs, + inspectors::CheatsConfig, + revm::primitives::SpecId, + traces::{render_trace_arena, CallTraceDecoderBuilder}, }; use foundry_test_utils::{init_tracing, Filter}; +use futures::future::join_all; use itertools::Itertools; use std::{collections::BTreeMap, path::Path}; @@ -78,14 +82,25 @@ impl TestConfig { { let logs = decode_console_logs(&result.logs); let outcome = if self.should_fail { "fail" } else { "pass" }; - + let call_trace_decoder = CallTraceDecoderBuilder::default().build(); + let decoded_traces = join_all( + result + .traces + .iter() + .map(|(_, a)| render_trace_arena(a, &call_trace_decoder)) + .collect::>(), + ) + .await + .into_iter() + .map(|x| x.unwrap()) + .collect::>(); eyre::bail!( "Test {} did not {} as expected.\nReason: {:?}\nLogs:\n{}\n\nTraces:\n{}", test_name, outcome, result.reason, logs.join("\n"), - result.traces.iter().map(|(_, a)| a).format("\n"), + decoded_traces.into_iter().format("\n"), ) } } From 29b0944748f7c6b8c25cd56b65edaef6cd353d4b Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 11 Dec 2023 17:45:37 +0100 Subject: [PATCH 08/13] derive debug --- crates/evm/traces/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index fd2e65e876db..5e7511ba639a 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -32,13 +32,13 @@ pub use reth_revm_inspectors::tracing::{ pub type Traces = Vec<(TraceKind, CallTraceArena)>; -#[derive(Default)] +#[derive(Default, Debug)] pub struct DecodedCallData { pub signature: String, pub args: Vec, } -#[derive(Default)] +#[derive(Default, Debug)] pub struct DecodedCallTrace { pub label: Option, pub return_data: Option, @@ -46,6 +46,7 @@ pub struct DecodedCallTrace { pub contract: Option, } +#[derive(Debug)] pub enum DecodedCallLog<'a> { /// A raw log. Raw(&'a Log), From 9121a7f918850cf0e32207667ee7e1ed2023e6ca Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 11 Dec 2023 17:45:48 +0100 Subject: [PATCH 09/13] fix contract identification --- crates/evm/traces/src/decoder/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index e7335bc2f14e..c65912277be4 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -168,8 +168,8 @@ impl CallTraceDecoder { .map(|node| { ( &node.trace.address, - if node.trace.kind == crate::CallKind::Create { - Some(node.trace.data.as_ref()) + if node.trace.kind.is_any_create() { + Some(node.trace.output.as_ref()) } else { None }, From 02f1fc2d86771b838932a91ae33d5069e07de9fd Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 11 Dec 2023 17:46:00 +0100 Subject: [PATCH 10/13] fix formatting --- crates/evm/traces/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 5e7511ba639a..0a661ae132da 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -151,7 +151,7 @@ pub async fn render_trace( decoder: &CallTraceDecoder, ) -> Result<(String, Option), std::fmt::Error> { let mut s = String::new(); - write!(&mut s, "[{}]", trace.gas_used)?; + write!(&mut s, "[{}] ", trace.gas_used)?; let address = trace.address.to_checksum(None); let decoded = decoder.decode_function(trace).await; From b770098730a7d59cddede675edee2cef14065937 Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 11 Dec 2023 17:46:53 +0100 Subject: [PATCH 11/13] remove stray todo --- crates/evm/traces/src/decoder/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index c65912277be4..ae23d5f23f81 100644 --- a/crates/evm/traces/src/decoder/mod.rs +++ b/crates/evm/traces/src/decoder/mod.rs @@ -226,7 +226,6 @@ impl CallTraceDecoder { } pub async fn decode_function(&self, trace: &CallTrace) -> DecodedCallTrace { - // todo: avoid decoding creates // Decode precompile if let Some((label, func)) = precompiles::decode(&trace, 1) { return DecodedCallTrace { From 47ab3d8f774841ed86bb0bf8d8f3db6130448bfa Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 11 Dec 2023 17:57:41 +0100 Subject: [PATCH 12/13] fix empty output --- crates/evm/traces/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 0a661ae132da..d44a91475a14 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -130,7 +130,11 @@ pub async fn render_trace_arena( } } } else { - writeln!(s, "{}", node.trace.output)?; + match &return_data { + None if node.trace.output.is_empty() => writeln!(s, "()")?, + None => writeln!(s, "{}", node.trace.output)?, + Some(val) => writeln!(s, "{val}")?, + } } Ok(()) From 3fe5a36fc50642490899b6f9b6cdd054a3921144 Mon Sep 17 00:00:00 2001 From: Oliver Nordbjerg Date: Mon, 11 Dec 2023 18:06:00 +0100 Subject: [PATCH 13/13] fix unrelated test :) --- crates/cheatcodes/src/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/cheatcodes/src/env.rs b/crates/cheatcodes/src/env.rs index b4a4a9a0c1f9..3bc5b6ee8f90 100644 --- a/crates/cheatcodes/src/env.rs +++ b/crates/cheatcodes/src/env.rs @@ -296,7 +296,7 @@ mod tests { let err = env(key, &DynSolType::Uint(256)).unwrap_err().to_string(); assert!(!err.contains(value)); - assert_eq!(err, "failed parsing $parse_env_uint as type `uint256`: parser error:\n$parse_env_uint\n ^\nexpected at least one digit"); + assert_eq!(err, "failed parsing $parse_env_uint as type `uint256`: parser error:\n$parse_env_uint\n^\nexpected at least one digit"); env::remove_var(key); } }