diff --git a/Cargo.lock b/Cargo.lock index 3713ccc80c95..a08d64154ac2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,11 +78,11 @@ 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", + "num_enum 0.7.1", "serde", "strum", ] @@ -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]] @@ -481,6 +481,7 @@ dependencies = [ "parking_lot", "pretty_assertions", "rand 0.8.5", + "reth-rpc-types", "serde", "serde_json", "serde_repr", @@ -514,6 +515,7 @@ dependencies = [ "keccak-hasher", "open-fastrlp", "reference-trie", + "reth-rpc-types", "revm", "serde", "serde_json", @@ -753,7 +755,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -770,7 +772,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -964,7 +966,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.39", + "syn 2.0.40", "which", ] @@ -1058,6 +1060,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.3", + "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.40", + "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" @@ -1381,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", @@ -1391,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", @@ -1432,7 +1572,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -1465,6 +1605,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" @@ -1519,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", @@ -1530,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", @@ -1656,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", @@ -1666,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" @@ -1750,6 +1892,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" @@ -1896,7 +2044,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -1907,7 +2055,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -1941,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", @@ -1968,7 +2116,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2084,6 +2232,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.40", +] + [[package]] name = "dotenvy" version = "0.15.7" @@ -2153,6 +2312,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" @@ -2209,7 +2374,7 @@ checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2407,7 +2572,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "syn 2.0.39", + "syn 2.0.40", "toml 0.8.8", "walkdir", ] @@ -2424,7 +2589,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2441,7 +2606,7 @@ dependencies = [ "ethabi", "generic-array", "k256", - "num_enum", + "num_enum 0.7.1", "once_cell", "open-fastrlp", "rand 0.8.5", @@ -2449,7 +2614,7 @@ dependencies = [ "serde", "serde_json", "strum", - "syn 2.0.39", + "syn 2.0.40", "tempfile", "thiserror", "tiny-keccak", @@ -2639,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", ] @@ -2683,7 +2854,7 @@ dependencies = [ "bytes", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -2699,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]] @@ -2746,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]] @@ -2927,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", @@ -3271,7 +3442,6 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "const-hex", - "ethers-core", "eyre", "foundry-block-explorers", "foundry-common", @@ -3283,7 +3453,7 @@ dependencies = [ "itertools 0.11.0", "once_cell", "ordered-float", - "revm", + "reth-revm-inspectors", "serde", "tempfile", "tokio", @@ -3298,7 +3468,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3309,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", @@ -3440,7 +3610,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -3548,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", @@ -3583,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", @@ -3596,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", @@ -3608,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", @@ -3622,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", @@ -3643,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", @@ -3653,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", @@ -3683,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", @@ -3717,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", @@ -3729,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", @@ -3742,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", @@ -3870,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" @@ -3984,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", @@ -4065,7 +4244,7 @@ dependencies = [ "futures-util", "http", "hyper", - "rustls 0.21.9", + "rustls 0.21.10", "tokio", "tokio-rustls 0.24.1", ] @@ -4106,6 +4285,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" @@ -4358,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" @@ -4518,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" @@ -4558,7 +4853,7 @@ checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ "bitflags 2.4.1", "libc", - "redox_syscall 0.4.1", + "redox_syscall", ] [[package]] @@ -4587,9 +4882,15 @@ 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" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d642685b028806386b2b6e75685faadd3eb65a85fff7df711ce18446a422da" [[package]] name = "lock_api" @@ -4651,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" @@ -4686,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", @@ -4702,6 +4997,7 @@ dependencies = [ "memchr", "once_cell", "opener", + "pathdiff", "pulldown-cmark", "regex", "serde", @@ -4785,7 +5081,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -4821,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", @@ -4964,6 +5260,7 @@ dependencies = [ "autocfg", "num-integer", "num-traits", + "serde", ] [[package]] @@ -5028,13 +5325,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.40", ] [[package]] @@ -5046,7 +5364,7 @@ dependencies = [ "proc-macro-crate 2.0.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5075,9 +5393,13 @@ 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 = [ + "critical-section", + "portable-atomic", +] [[package]] name = "oorandom" @@ -5129,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", @@ -5150,7 +5472,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5161,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", @@ -5179,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", ] @@ -5260,7 +5582,7 @@ checksum = "f557c32c6d268a07c921471619c0295f5efad3a0e76d4f97a05c091a51d110b2" dependencies = [ "proc-macro2", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -5287,7 +5609,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall", "smallvec", "windows-targets 0.48.5", ] @@ -5315,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" @@ -5357,7 +5685,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5412,7 +5740,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5515,7 +5843,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5553,7 +5881,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -5623,11 +5951,28 @@ 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" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[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" @@ -5664,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]] @@ -5741,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", ] @@ -5974,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" @@ -6067,6 +6403,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" @@ -6092,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", @@ -6111,6 +6457,41 @@ dependencies = [ "winreg", ] +[[package]] +name = "reth-revm-inspectors" +version = "0.1.0-alpha.13" +source = "git+https://github.com/paradigmxyz/reth/?branch=main#fa1584b22306f6f0573a5d4c85f77a685c3e65d4" +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.13" +source = "git+https://github.com/paradigmxyz/reth/?branch=main#fa1584b22306f6f0573a5d4c85f77a685c3e65d4" +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" @@ -6143,7 +6524,7 @@ dependencies = [ "once_cell", "revm-primitives", "ripemd", - "secp256k1", + "secp256k1 0.28.0", "sha2 0.10.8", "substrate-bn", ] @@ -6192,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", @@ -6418,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]] @@ -6443,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", ] @@ -6480,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", ] @@ -6527,9 +6908,15 @@ 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" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6518fc26bced4d53678a22d6e423e9d8716377def84545fe328236e3af070e7f" [[package]] name = "salsa20" @@ -6630,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", ] @@ -6648,20 +7035,39 @@ 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.1", ] [[package]] name = "secp256k1-sys" -version = "0.9.0" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09e67c467c38fd24bd5499dc9a18183b31575c12ee549197e3e20d57aa4fe3b7" +checksum = "4dd97a086ec737e30053fd5c46f097465d25bb81dd3608825f65298c4c98be83" dependencies = [ "cc", ] @@ -6745,7 +7151,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6799,7 +7205,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6849,7 +7255,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -6874,7 +7280,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7102,6 +7508,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" @@ -7165,7 +7583,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7233,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", @@ -7251,7 +7669,7 @@ dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7272,6 +7690,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.40", + "unicode-xid", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -7307,7 +7737,7 @@ checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "redox_syscall", "rustix", "windows-sys 0.48.0", ] @@ -7366,6 +7796,12 @@ dependencies = [ "phf_codegen 0.11.2", ] +[[package]] +name = "thin-vec" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" + [[package]] name = "thiserror" version = "1.0.50" @@ -7383,7 +7819,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7445,6 +7881,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" @@ -7478,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", @@ -7503,7 +7950,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7533,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", ] @@ -7557,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", @@ -7724,7 +8171,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", ] [[package]] @@ -7835,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" @@ -7853,7 +8300,7 @@ dependencies = [ "log", "native-tls", "rand 0.8.5", - "rustls 0.21.9", + "rustls 0.21.10", "sha1", "thiserror", "url", @@ -7911,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" @@ -7983,6 +8430,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" version = "0.2.1" @@ -8090,7 +8549,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "wasm-bindgen-shared", ] @@ -8124,7 +8583,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -8199,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", ] @@ -8470,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", ] @@ -8487,6 +8946,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" @@ -8533,24 +9004,69 @@ 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.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 = "be912bf68235a88fbefd1b73415cb218405958d1655b2ece9035a19920bdf6ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.40", +] + +[[package]] +name = "zerofrom" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +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", + "syn 2.0.40", + "synstructure 0.13.0", ] [[package]] @@ -8570,7 +9086,30 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.40", +] + +[[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.40", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0e6b6a87ec3c..01147f3731f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -123,7 +123,9 @@ foundry-evm-traces = { path = "crates/evm/traces" } foundry-macros = { path = "crates/macros" } foundry-test-utils = { path = "crates/test-utils" } +# block explorer & verification bindings foundry-block-explorers = { version = "0.1.1", default-features = false } +# solc & compilation utilities foundry-compilers = { version = "0.1.1", default-features = false } ## revm @@ -216,6 +218,6 @@ alloy-rpc-client = { git = "https://github.com/alloy-rs/alloy/", branch = "onbje alloy-json-rpc = { git = "https://github.com/alloy-rs/alloy/", branch = "onbjerg/alloy-temp-provider-trait" } revm = { 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-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" } \ No newline at end of file diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 112dc1c9e134..ef46ca371306 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -39,6 +39,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 = "main" } + # axum related axum.workspace = true diff --git a/crates/anvil/core/Cargo.toml b/crates/anvil/core/Cargo.toml index 60ba15cb5495..8ddad4a71959 100644 --- a/crates/anvil/core/Cargo.toml +++ b/crates/anvil/core/Cargo.toml @@ -26,6 +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 = "main" } # 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 1eb0a3eeaa56..af803062f045 100644 --- a/crates/anvil/core/src/eth/mod.rs +++ b/crates/anvil/core/src/eth/mod.rs @@ -8,7 +8,8 @@ use alloy_rpc_types::{ state::StateOverride, BlockId, BlockNumberOrTag as BlockNumber, CallRequest, Filter, }; -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; @@ -261,7 +262,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 @@ -269,7 +270,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` diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index 7d7122ecd6b1..ba89b1e6c00a 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -15,7 +15,7 @@ use ethers_core::{ }, }; use foundry_common::types::ToAlloy; -use foundry_evm::traces::CallTraceArena; +use foundry_evm::traces::CallTraceNode; use revm::{ interpreter::InstructionResult, primitives::{CreateScheme, OptimismFields, TransactTo, TxEnv}, @@ -1513,47 +1513,12 @@ 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, pub nonce: u64, } -// === 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 b1653ef8d0b5..2fe611330be5 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -47,7 +47,7 @@ use alloy_rpc_types::{ TransactionReceipt, TxpoolContent, TxpoolInspect, - // trace::{geth::{DefaultFrame, GethDebugTracingOptions, GethTrace}, + // trace::{geth::{DefaultFrame, GethDefaultTracingOptions, GethTrace}, // parity::LocalizedTransactionTrace}, TxpoolInspectSummary, TxpoolStatus, @@ -69,11 +69,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, types::{ToAlloy, ToEthers}, @@ -88,6 +84,10 @@ use foundry_evm::{ }; 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}` @@ -1456,13 +1456,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 } @@ -1473,12 +1469,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()), @@ -1495,7 +1488,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 } @@ -1503,7 +1496,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 } diff --git a/crates/anvil/src/eth/backend/executor.rs b/crates/anvil/src/eth/backend/executor.rs index 650954c93ce9..5f2069a5a8e9 100644 --- a/crates/anvil/src/eth/backend/executor.rs +++ b/crates/anvil/src/eth/backend/executor.rs @@ -20,12 +20,13 @@ use ethers::{ use foundry_common::types::{ToAlloy, ToEthers}; use foundry_evm::{ backend::DatabaseError, + inspectors::{TracingInspector, TracingInspectorConfig}, revm, revm::{ 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 std::sync::Arc; @@ -171,7 +172,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)), @@ -321,7 +322,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(), nonce, }; diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index 295558408ba3..5e3126d7b613 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -5,19 +5,20 @@ 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}, primitives::{Address, Bytes, B256}, EVMData, }, + traces::TracingInspectorConfig, }; /// 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, } @@ -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 83bdcc6fdf8d..d2c6bf6777d0 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, @@ -63,11 +63,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}; @@ -86,12 +82,17 @@ 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 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::{BTreeMap, HashMap}, io::{Read, Write}, @@ -1142,7 +1143,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(); @@ -1166,7 +1167,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) }) @@ -1832,7 +1836,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); } @@ -1845,7 +1852,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()) } @@ -1855,7 +1865,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(); @@ -1869,29 +1882,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); diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index dd70cf2259c4..980f362bac08 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -13,13 +13,19 @@ use anvil_core::eth::{ receipt::TypedReceipt, transaction::{MaybeImpersonatedTransaction, TransactionInfo}, }; -use ethers::{ - prelude::{DefaultFrame, Trace}, - types::{ActionType, GethDebugTracingOptions}, -}; use foundry_common::types::{ToAlloy, ToEthers}; -use foundry_evm::revm::{interpreter::InstructionResult, primitives::Env}; +use foundry_evm::{ + revm::primitives::Env, + traces::{GethTraceBuilder, ParityTraceBuilder, TracingInspectorConfig}, +}; 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 +402,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 907e37c12392..b0cf7cd7e4b9 100644 --- a/crates/anvil/src/eth/otterscan/api.rs +++ b/crates/anvil/src/eth/otterscan/api.rs @@ -9,9 +9,10 @@ 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_common::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 +151,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 +204,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 +272,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 df6cbef13290..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_common::types::ToAlloy; -use foundry_evm::{revm::interpreter::InstructionResult, utils::CallKind}; +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; @@ -263,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, @@ -304,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 { @@ -323,7 +321,7 @@ impl OtsTrace { } } Action::Create(_) => None, - Action::Suicide(_) => None, + Action::Selfdestruct(_) => None, Action::Reward(_) => None, }) .collect() 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/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); } } diff --git a/crates/chisel/src/dispatcher.rs b/crates/chisel/src/dispatcher.rs index b191d8dccad3..66925fd3269d 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_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, }, }; use once_cell::sync::Lazy; @@ -983,11 +983,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/common/src/compile.rs b/crates/common/src/compile.rs index 873ece4349ea..749ef15f2388 100644 --- a/crates/common/src/compile.rs +++ b/crates/common/src/compile.rs @@ -150,10 +150,10 @@ impl ProjectCompiler { let dev_functions = artifact.abi.as_ref().map(|abi| abi.functions()).into_iter().flatten().filter( - |&func| { + |func| { func.name.is_test() || - func.name == "IS_TEST" || - func.name == "IS_SCRIPT" + func.name.eq("IS_TEST") || + func.name.eq("IS_SCRIPT") }, ); 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/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index dcb1682883fa..f9ad0c32ce9b 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -557,7 +557,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() }, @@ -567,7 +567,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/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 d72d2ef0eed5..4219cc979928 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; @@ -207,7 +207,7 @@ pub struct InspectorStack { pub fuzzer: Option, pub log_collector: Option, pub printer: Option, - pub tracer: Option, + pub tracer: Option, } impl InspectorStack { @@ -289,7 +289,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. @@ -304,7 +314,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 7e11d23f8f54..d3fe2338e9b3 100644 --- a/crates/evm/traces/Cargo.toml +++ b/crates/evm/traces/Cargo.toml @@ -21,9 +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 -revm.workspace = true - -ethers-core.workspace = true +reth-revm-inspectors = { git = "https://github.com/paradigmxyz/reth/", branch = "main" } eyre = "0.6" futures = "0.3" diff --git a/crates/evm/traces/src/decoder/mod.rs b/crates/evm/traces/src/decoder/mod.rs index 2866d8319a39..ae23d5f23f81 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}, - CallTrace, CallTraceArena, TraceCallData, TraceLog, TraceRetData, + CallTrace, CallTraceArena, DecodedCallData, DecodedCallLog, 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, HardhatConsole, Vm}, @@ -160,11 +160,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.is_any_create() { + Some(node.trace.output.as_ref()) + } else { + None + }, + ) + }) + .filter(|(address, _)| { + !self.labels.contains_key(*address) || !self.contracts.contains_key(*address) + }) } fn collect_identities(&mut self, identities: Vec>) { @@ -212,41 +225,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 { // 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, + contract: 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() { - if let Some(contract) = self.contracts.get(&trace.address) { - trace.contract = Some(contract.clone()); - } - } - - let TraceCallData::Raw(cdata) = &trace.data else { return }; + let contract = self.contracts.get(&trace.address).cloned(); + 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, + contract, + func: Some(DecodedCallData { signature: "create2".to_string(), args: vec![] }), + }; } if cdata.len() >= SELECTOR_LEN { @@ -265,48 +268,58 @@ 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, 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); 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 + }, + contract, + 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. @@ -375,15 +388,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) } } @@ -393,18 +405,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))) } } @@ -421,26 +432,25 @@ impl CallTraceDecoder { } /// Decodes an event. - async fn decode_event(&self, log: &mut TraceLog) { - 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() @@ -452,9 +462,10 @@ impl CallTraceDecoder { }) .collect(), ); - break } } + + DecodedCallLog::Raw(log) } 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 3d88ee23ff1e..d44a91475a14 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -6,22 +6,12 @@ #[macro_use] extern crate tracing; - -use alloy_primitives::{Address, Bytes, Log as RawLog, B256, U256}; -use ethers_core::types::{DefaultFrame, GethDebugTracingOptions, StructLog}; -use foundry_common::{ - contracts::{ContractsByAddress, ContractsByArtifact}, - types::ToEthers, -}; -use foundry_evm_core::{constants::CHEATCODE_ADDRESS, debug::Instruction, utils::CallKind}; -use hashbrown::HashMap; -use itertools::Itertools; -use revm::interpreter::{opcode, CallContext, InstructionResult, Stack}; +use alloy_primitives::{Log, U256}; +use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact}; +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. @@ -33,160 +23,38 @@ use identifier::LocalTraceIdentifier; mod decoder; pub use decoder::{CallTraceDecoder, CallTraceDecoderBuilder}; -mod inspector; -pub use inspector::Tracer; - -mod node; -pub use node::CallTraceNode; +use reth_revm_inspectors::tracing::types::LogCallOrder; +pub use reth_revm_inspectors::tracing::{ + types::{CallKind, CallTrace, CallTraceNode}, + CallTraceArena, GethTraceBuilder, ParityTraceBuilder, StackSnapshotType, TracingInspector, + TracingInspectorConfig, +}; 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, +#[derive(Default, Debug)] +pub struct DecodedCallData { + pub signature: String, + pub args: Vec, } -impl Default for CallTraceArena { - fn default() -> Self { - CallTraceArena { arena: vec![Default::default()] } - } +#[derive(Default, Debug)] +pub struct DecodedCallTrace { + pub label: Option, + pub return_data: Option, + pub func: Option, + pub contract: Option, } -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().to_ethers(), - ..Default::default() - }; - - self.add_to_geth_trace(&mut storage, main_trace_node, &mut acc.struct_logs, &opts); - - acc - } +#[derive(Debug)] +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 = " │ "; @@ -195,19 +63,27 @@ 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]; +/// 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 - writeln!(f, "{left}{}", node.trace)?; + let (trace, return_data) = render_trace(&node.trace, decoder).await?; + writeln!(s, "{left}{}", trace)?; // Display logs and subcalls let left_prefix = format!("{child}{BRANCH}"); @@ -215,11 +91,12 @@ impl fmt::Display for CallTraceArena { 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)| { writeln!( - f, + s, "{}{}", if i == 0 { &left_prefix } else { &right_prefix }, line @@ -227,332 +104,146 @@ impl fmt::Display for CallTraceArena { })?; } LogCallOrder::Call(index) => { - inner(arena, f, node.children[*index], &left_prefix, &right_prefix)?; + inner( + arena, + decoder, + s, + node.children[*index], + &left_prefix, + &right_prefix, + ) + .await?; } } } // 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())?; + 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())?; } - TraceRetData::Decoded(val) => { - writeln!(f, "{val}")?; + Some(val) => { + writeln!(s, "{val}")?; } } } else { - writeln!(f, "{}", 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(()) } - - inner(self, f, 0, " ", " ") + .boxed() } -} -/// 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)>), + let mut s = String::new(); + inner(arena.nodes(), decoder, &mut s, 0, " ", " ").await?; + Ok(s) } -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 +/// Render a call trace. /// -/// 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, "()") +/// 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 { - bytes.fmt(f) + let (selector, data) = trace.data.split_at(4); + (hex::encode(selector), hex::encode(data)) } } - 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: Vec, - /// 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, -} + let action = match trace.kind { + CallKind::Call => "", + CallKind::StaticCall => " [staticcall]", + CallKind::CallCode => " [callcode]", + CallKind::DelegateCall => " [delegatecall]", + CallKind::Create | CallKind::Create2 => unreachable!(), + }; -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)), - op: step.op.to_string(), - pc: step.pc as u64, - refund_counter: if step.gas_refund_counter > 0 { - Some(step.gas_refund_counter) + 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 { - None + format!("{{value: {}}}", trace.value) }, - 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, - } + action = Paint::yellow(action), + )?; } -} -/// 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, + Ok((s, decoded.return_data)) } -impl CallTrace { - /// Whether this is a contract creation or not - pub fn created(&self) -> bool { - matches!(self.kind, CallKind::Create | CallKind::Create2) - } -} +/// 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:?}")) + )?; + } -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(), + write!(s, " data: {}", Paint::cyan(hex::encode_prefixed(&log.data)))?; } - } -} - -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), - ) + 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. @@ -623,36 +314,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/inspect.rs b/crates/forge/bin/cmd/inspect.rs index f1c4e0903505..2c3911774556 100644 --- a/crates/forge/bin/cmd/inspect.rs +++ b/crates/forge/bin/cmd/inspect.rs @@ -165,6 +165,7 @@ impl InspectArgs { ContractArtifactField::Errors => { let mut out = serde_json::Map::new(); if let Some(abi) = &artifact.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::>(); @@ -181,6 +182,8 @@ impl InspectArgs { ContractArtifactField::Events => { let mut out = serde_json::Map::new(); if let Some(abi) = &artifact.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/script/executor.rs b/crates/forge/bin/cmd/script/executor.rs index a5753fdce4c2..70dbadaeb4e8 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::{ @@ -170,13 +169,13 @@ 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().into(), - }) + init_code: node.trace.data.clone(), + }); } None }) @@ -222,7 +221,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 { @@ -233,9 +232,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 5339973d283b..c4df4f40f7e9 100644 --- a/crates/forge/bin/cmd/script/mod.rs +++ b/crates/forge/bin/cmd/script/mod.rs @@ -18,9 +18,8 @@ use forge::{ opts::EvmOpts, traces::{ identifier::{EtherscanIdentifier, LocalTraceIdentifier, SignaturesIdentifier}, - CallTraceDecoder, CallTraceDecoderBuilder, TraceCallData, TraceKind, TraceRetData, Traces, + render_trace_arena, CallTraceDecoder, CallTraceDecoderBuilder, TraceKind, Traces, }, - utils::CallKind, }; use foundry_cli::opts::MultiWallet; use foundry_common::{ @@ -296,7 +295,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, @@ -304,8 +303,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())?; @@ -503,27 +501,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; diff --git a/crates/forge/bin/cmd/script/runner.rs b/crates/forge/bin/cmd/script/runner.rs index 592501cc5541..9144bfaf52c1 100644 --- a/crates/forge/bin/cmd/script/runner.rs +++ b/crates/forge/bin/cmd/script/runner.rs @@ -239,9 +239,10 @@ 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 - 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(), @@ -300,9 +301,10 @@ 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 - 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 a31c9e80a607..eb8010a60e68 100644 --- a/crates/forge/bin/cmd/script/transaction.rs +++ b/crates/forge/bin/cmd/script/transaction.rs @@ -10,7 +10,10 @@ use foundry_common::{ types::{ToAlloy, ToEthers}, SELECTOR_LEN, }; -use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, traces::CallTraceDecoder, utils::CallKind}; +use foundry_evm::{ + constants::DEFAULT_CREATE2_DEPLOYER, + traces::{CallKind, CallTraceDecoder}, +}; 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 42040a03744f..82c876c30246 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; @@ -261,31 +264,9 @@ 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); - - 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?); } } @@ -737,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 2fb0ff46a34e..fc2a4c7652b7 100644 --- a/crates/forge/src/gas_report.rs +++ b/crates/forge/src/gas_report.rs @@ -3,7 +3,7 @@ use crate::{ constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS}, hashbrown::HashSet, - traces::{CallTraceArena, TraceCallData, TraceKind}, + traces::{CallTraceArena, CallTraceDecoder, CallTraceNode, DecodedCallData, TraceKind}, }; use alloy_primitives::U256; use comfy_table::{presets::ASCII_MARKDOWN, *}; @@ -46,21 +46,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) { - 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,35 +82,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. diff --git a/crates/forge/src/result.rs b/crates/forge/src/result.rs index 604fbb698302..601cd27de7f2 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 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"), ) } }