diff --git a/Cargo.lock b/Cargo.lock index 37ddf3367eded..d5d411c5c5da6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,9 +70,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fbf458101ed6c389e9bb70a34ebc56039868ad10472540614816cdedc8f5265" +checksum = "27d301f5bcfd37e3aac727c360d8b50c33ddff9169ce0370198dedda36a9927d" dependencies = [ "alloy-eips", "alloy-primitives", @@ -93,9 +93,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc982af629e511292310fe85b433427fd38cb3105147632b574abc997db44c91" +checksum = "9f4f97a85a45965e0e4f9f5b94bbafaa3e4ee6868bdbcf2e4a9acb4b358038fe" dependencies = [ "alloy-consensus", "alloy-eips", @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0a0c1ddee20ecc14308aae21c2438c994df7b39010c26d70f86e1d8fdb8db0" +checksum = "f39e8b96c9e25dde7222372332489075f7e750e4fd3e81c11eec0939b78b71b8" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -145,7 +145,7 @@ dependencies = [ "proptest", "serde", "serde_json", - "winnow 0.7.9", + "winnow 0.7.10", ] [[package]] @@ -169,8 +169,6 @@ checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" dependencies = [ "alloy-primitives", "alloy-rlp", - "arbitrary", - "rand 0.8.5", "serde", ] @@ -182,18 +180,16 @@ checksum = "9b15b13d38b366d01e818fe8e710d4d702ef7499eacd44926a06171dd9585d0c" dependencies = [ "alloy-primitives", "alloy-rlp", - "arbitrary", "k256", - "rand 0.8.5", "serde", "thiserror 2.0.12", ] [[package]] name = "alloy-eips" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e86967eb559920e4b9102e4cb825fe30f2e9467988353ce4809f0d3f2c90cd4" +checksum = "10b11c382ca8075128d1ae6822b60921cf484c911d9a5831797a01218f98125f" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -205,16 +201,34 @@ dependencies = [ "c-kzg", "derive_more 2.0.1", "either", - "once_cell", "serde", - "sha2", + "sha2 0.10.9", +] + +[[package]] +name = "alloy-evm" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71b0b181c956dca015b4c08b36668736013787c9dc9e743fd39a23b8b130c14" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-hardforks", + "alloy-primitives", + "alloy-sol-types", + "auto_impl", + "derive_more 2.0.1", + "op-alloy-consensus", + "op-revm", + "revm", + "thiserror 2.0.12", ] [[package]] name = "alloy-genesis" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40de6f5b53ecf5fd7756072942f41335426d9a3704cd961f77d854739933bcf" +checksum = "7bd9e75c5dd40319ebbe807ebe9dfb10c24e4a70d9c7d638e62921d8dd093c8b" dependencies = [ "alloy-eips", "alloy-primitives", @@ -223,6 +237,19 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-hardforks" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "473ee2ab7f5262b36e8fbc1b5327d5c9d488ab247e31ac739b929dbe2444ae79" +dependencies = [ + "alloy-chains", + "alloy-eip2124", + "alloy-primitives", + "auto_impl", + "dyn-clone", +] + [[package]] name = "alloy-json-abi" version = "0.8.25" @@ -237,9 +264,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27434beae2514d4a2aa90f53832cbdf6f23e4b5e2656d95eaf15f9276e2418b6" +checksum = "bbcf26d02a72e23d5bc245425ea403c93ba17d254f20f9c23556a249c6c7e143" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -251,9 +278,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a33a38c7486b1945f8d093ff027add2f3a8f83c7300dbad6165cc49150085e" +checksum = "b44dd4429e190f727358571175ebf323db360a303bf4e1731213f510ced1c2e6" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -277,9 +304,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db973a7a23cbe96f2958e5687c51ce2d304b5c6d0dc5ccb3de8667ad8476f50b" +checksum = "86f736e1d1eb1b770dbd32919bdf46d4dcd4617f2eed07947dfb32649962baba" dependencies = [ "alloy-consensus", "alloy-eips", @@ -288,6 +315,33 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-op-evm" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324cf0b3b08b4c3354460dee8208384a59245da8b0eaefe9e962d3942d919d58" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-evm", + "alloy-op-hardforks", + "alloy-primitives", + "auto_impl", + "op-alloy-consensus", + "op-revm", + "revm", +] + +[[package]] +name = "alloy-op-hardforks" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "217a4efe17c43df77c1f261825350be0be1d907f56eb38a4b258936e33cfd1d8" +dependencies = [ + "alloy-hardforks", + "auto_impl", +] + [[package]] name = "alloy-primitives" version = "0.8.25" @@ -321,9 +375,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b03bde77ad73feae14aa593bcabb932c8098c0f0750ead973331cfc0003a4e1" +checksum = "a557f9e3ec89437b06db3bfc97d20782b1f7cc55b5b602b6a82bf3f64d7efb0e" dependencies = [ "alloy-chains", "alloy-consensus", @@ -338,6 +392,7 @@ dependencies = [ "alloy-rpc-types-eth", "alloy-rpc-types-trace", "alloy-rpc-types-txpool", + "alloy-signer", "alloy-sol-types", "alloy-transport", "alloy-transport-http", @@ -347,6 +402,7 @@ dependencies = [ "async-trait", "auto_impl", "dashmap", + "either", "futures", "futures-utils-wasm", "lru 0.13.0", @@ -364,15 +420,16 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721aca709a9231815ad5903a2d284042cc77e7d9d382696451b30c9ee0950001" +checksum = "f0a261caff6c2ec6fe1d6eb77ba41159024c8387d05e4138804a387d403def55" dependencies = [ "alloy-json-rpc", "alloy-primitives", "alloy-transport", "bimap", "futures", + "parking_lot", "serde", "serde_json", "tokio", @@ -405,9 +462,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445a3298c14fae7afb5b9f2f735dead989f3dd83020c2ab8e48ed95d7b6d1acb" +checksum = "cec6dc89c4c3ef166f9fa436d1831f8142c16cf2e637647c936a6aaaabd8d898" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -433,9 +490,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9157deaec6ba2ad7854f16146e4cd60280e76593eed79fdcb06e0fa8b6c60f77" +checksum = "3849f8131a18cc5d7f95f301d68a6af5aa2db28ad8522fb9db1f27b3794e8b68" dependencies = [ "alloy-primitives", "alloy-rpc-types-anvil", @@ -449,9 +506,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-anvil" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a80ee83ef97e7ffd667a81ebdb6154558dfd5e8f20d8249a10a12a1671a04b3" +checksum = "19051fd5e8de7e1f95ec228c9303debd776dcc7caf8d1ece3191f711f5c06541" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -461,9 +518,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604dea1f00fd646debe8033abe8e767c732868bf8a5ae9df6321909ccbc99c56" +checksum = "ecd6d480e4e6e456f30eeeb3aef1512aaecb68df2a35d1f78865dbc4d20dc0fd" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -472,9 +529,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-debug" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08b113a0087d226291b9768ed331818fa0b0744cc1207ae7c150687cf3fde1bd" +checksum = "805eb9fa07f92f1225253e842b5454b4b3e258813445c1a1c9d8dd0fd90817c1" dependencies = [ "alloy-primitives", "serde", @@ -482,9 +539,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874ac9d1249ece0453e262d9ba72da9dbb3b7a2866220ded5940c2e47f1aa04d" +checksum = "689521777149dabe210ef122605fb00050e038f2e85b8c9897534739f1a904f8" dependencies = [ "alloy-consensus", "alloy-eips", @@ -500,9 +557,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e13d71eac04513a71af4b3df580f52f2b4dcbff9d971cc9a52519acf55514cb" +checksum = "9a8b6d55bdaa0c4a08650d4b32f174494cbade56adf6f2fcfa2a4f3490cb5511" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -520,9 +577,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4747763aee39c1b0f5face79bde9be8932be05b2db7d8bdcebb93490f32c889c" +checksum = "6019cd6a89230d765a621a7b1bc8af46a6a9cde2d2e540e6f9ce930e0fb7c6db" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -534,9 +591,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-txpool" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70132ebdbea1eaa68c4d6f7a62c2fadf0bdce83b904f895ab90ca4ec96f63468" +checksum = "ee36e5404642696af511f09991f9f54a11b90e86e55efad868f8f56350eff5b0" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -546,9 +603,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a1cd73fc054de6353c7f22ff9b846b0f0f145cd0112da07d4119e41e9959207" +checksum = "1824791912f468a481dedc1db50feef3e85a078f6d743a62db2ee9c2ca674882" dependencies = [ "alloy-primitives", "serde", @@ -557,9 +614,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96fbde54bee943cd94ebacc8a62c50b38c7dfd2552dcd79ff61aea778b1bfcc" +checksum = "3d087fe5aea96a93fbe71be8aaed5c57c3caac303c09e674bc5b1647990d648b" dependencies = [ "alloy-dyn-abi", "alloy-primitives", @@ -574,9 +631,9 @@ dependencies = [ [[package]] name = "alloy-signer-aws" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e73835ed6689740b76cab0f59afbdce374a03d3f856ea33ba1fc054630a1b28" +checksum = "6623e424e692388d0c42071ed997513d7a19d8b83e83732466c0c93aedd486bd" dependencies = [ "alloy-consensus", "alloy-network", @@ -592,9 +649,9 @@ dependencies = [ [[package]] name = "alloy-signer-gcp" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a16b468ae86bb876d9c7a3b49b1e8d614a581a1a9673e4e0d2393b411080fe64" +checksum = "53755624ad8fbd12be2dc2e9df31cbab38e4067fa3d4ba02814145535a221f98" dependencies = [ "alloy-consensus", "alloy-network", @@ -610,9 +667,9 @@ dependencies = [ [[package]] name = "alloy-signer-ledger" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cf8a7f45edcc43566218e44b70ed3c278b7556926158cfeb63c8d41fefef70" +checksum = "d4224cd9c7b8107b1f7973361e81cf75e20a99835bcdc6ba7ac8ea50a6256e47" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -630,9 +687,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6e72002cc1801d8b41e9892165e3a6551b7bd382bd9d0414b21e90c0c62551" +checksum = "2940353d2425bb75965cd5101075334e6271051e35610f903bf8099a52b0b1a9" dependencies = [ "alloy-consensus", "alloy-network", @@ -649,9 +706,9 @@ dependencies = [ [[package]] name = "alloy-signer-trezor" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d4fd403c53cf7924c3e16c61955742cfc3813188f0975622f4fa6f8a01760aa" +checksum = "3bafd519704c7d9f2c449686e895a7681e5e7172bfef3f2d3ad8d0b4476d6f9d" dependencies = [ "alloy-consensus", "alloy-network", @@ -722,7 +779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d162f8524adfdfb0e4bd0505c734c985f3e2474eb022af32eef0d52a4f3935c" dependencies = [ "serde", - "winnow 0.7.9", + "winnow 0.7.10", ] [[package]] @@ -740,9 +797,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec325c2af8562ef355c02aeb527c755a07e9d8cf6a1e65dda8d0bf23e29b2c" +checksum = "6818b4c82a474cc01ac9e88ccfcd9f9b7bc893b2f8aea7e890a28dcd55c0a7aa" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -762,9 +819,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a082c9473c6642cce8b02405a979496126a03b096997888e86229afad05db06c" +checksum = "4cc3079a33483afa1b1365a3add3ea3e21c75b10f704870198ba7846627d10f2" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -777,9 +834,9 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a78cfda2cac16fa83f6b5dd8b4643caec6161433b25b67e484ce05d2194513" +checksum = "66c6f8e20aa6b748357bed157c14e561a176d0f6cffed7f99ee37758a7d16202" dependencies = [ "alloy-json-rpc", "alloy-pubsub", @@ -797,9 +854,9 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.12.6" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae865917bdabaae21f418010fe7e8837c6daa6611fde25f8d78a1778d6ecb523" +checksum = "5ef7a4301e8967c1998f193755fd9429e0ca81730e2e134e30c288c43dbf96f0" dependencies = [ "alloy-pubsub", "alloy-transport", @@ -949,8 +1006,10 @@ dependencies = [ "alloy-contract", "alloy-dyn-abi", "alloy-eips", + "alloy-evm", "alloy-genesis", "alloy-network", + "alloy-op-evm", "alloy-primitives", "alloy-provider", "alloy-pubsub", @@ -979,12 +1038,14 @@ dependencies = [ "foundry-common", "foundry-config", "foundry-evm", + "foundry-evm-core", "foundry-test-utils", "futures", "hyper", "itertools 0.14.0", "op-alloy-consensus", "op-alloy-rpc-types", + "op-revm", "parking_lot", "rand 0.8.5", "revm", @@ -995,7 +1056,7 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.19", "yansi", ] @@ -1015,6 +1076,7 @@ dependencies = [ "foundry-common", "foundry-evm", "op-alloy-consensus", + "op-revm", "rand 0.8.5", "revm", "serde", @@ -1076,6 +1138,51 @@ dependencies = [ "yansi", ] +[[package]] +name = "ark-bls12-381" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df4dcc01ff89867cd86b0da835f23c3f02738353aaee7dde7495af71363b8d5" +dependencies = [ + "ark-ec", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff 0.5.0", + "ark-r1cs-std", + "ark-std 0.5.0", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-poly", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.3", + "itertools 0.13.0", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] + [[package]] name = "ark-ff" version = "0.3.0" @@ -1114,6 +1221,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm 0.5.0", + "ark-ff-macros 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "educe", + "itertools 0.13.0", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + [[package]] name = "ark-ff-asm" version = "0.3.0" @@ -1134,6 +1261,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.101", +] + [[package]] name = "ark-ff-macros" version = "0.3.0" @@ -1159,6 +1296,63 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", + "ark-std 0.5.0", + "educe", + "fnv", + "hashbrown 0.15.3", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" +dependencies = [ + "ark-ec", + "ark-ff 0.5.0", + "ark-relations", + "ark-std 0.5.0", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + +[[package]] +name = "ark-relations" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" +dependencies = [ + "ark-ff 0.5.0", + "ark-std 0.5.0", + "tracing", + "tracing-subscriber 0.2.25", +] + [[package]] name = "ark-serialize" version = "0.3.0" @@ -1180,6 +1374,30 @@ dependencies = [ "num-bigint", ] +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive", + "ark-std 0.5.0", + "arrayvec", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "ark-std" version = "0.3.0" @@ -1200,6 +1418,22 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + [[package]] name = "arrayvec" version = "0.7.6" @@ -1434,9 +1668,9 @@ dependencies = [ [[package]] name = "aws-sdk-kms" -version = "1.66.0" +version = "1.67.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655097cd83ab1f15575890943135192560f77097413c6dd1733fdbdc453e81ac" +checksum = "2b650cf9e1e153ab13acd3aa1f73b271dac14e019353ec0b0c176f24a21bad03" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1457,9 +1691,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.65.0" +version = "1.66.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8efec445fb78df585327094fcef4cad895b154b58711e504db7a93c41aa27151" +checksum = "858007b14d0f1ade2e0124473c2126b24d334dc9486ad12eb7c0ed14757be464" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1480,9 +1714,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.66.0" +version = "1.67.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e49cca619c10e7b002dc8e66928ceed66ab7f56c1a3be86c5437bf2d8d89bba" +checksum = "b83abf3ae8bd10a014933cc2383964a12ca5a3ebbe1948ad26b1b808e7d0d1f2" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1503,9 +1737,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.66.0" +version = "1.67.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7420479eac0a53f776cc8f0d493841ffe58ad9d9783f3947be7265784471b47a" +checksum = "74e8e9ac4a837859c8f1d747054172e1e55933f02ed34728b0b34dea0591ec84" dependencies = [ "aws-credential-types", "aws-runtime", @@ -1542,7 +1776,7 @@ dependencies = [ "http 0.2.12", "http 1.3.1", "percent-encoding", - "sha2", + "sha2 0.10.9", "time", "tracing", ] @@ -1776,9 +2010,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -1873,6 +2107,22 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -1885,7 +2135,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" dependencies = [ - "arbitrary", "serde", ] @@ -1902,6 +2151,15 @@ dependencies = [ "wyz", ] +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -1954,7 +2212,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ - "sha2", + "sha2 0.10.9", "tinyvec", ] @@ -2033,10 +2291,11 @@ dependencies = [ [[package]] name = "c-kzg" -version = "1.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0307f72feab3300336fb803a57134159f6e20139af1357f36c54cb90d8e8928" +checksum = "4e7e3c397401eb76228c89561cf22f85f41c95aa799ee9d860de3ea1cbc728fc" dependencies = [ + "arbitrary", "blst", "cc", "glob", @@ -2088,6 +2347,7 @@ dependencies = [ "foundry-compilers", "foundry-config", "foundry-evm", + "foundry-evm-core", "foundry-test-utils", "foundry-wallets", "futures", @@ -2096,6 +2356,7 @@ dependencies = [ "rand 0.8.5", "rayon", "regex", + "revm", "rpassword", "semver 1.0.26", "serde", @@ -2176,7 +2437,7 @@ dependencies = [ "time", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.19", "walkdir", "yansi", ] @@ -2279,9 +2540,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.48" +version = "4.5.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8c97f3a6f02b9e24cadc12aaba75201d18754b53ea0a9d99642f806ccdb4c9" +checksum = "c91d3baa3bcd889d60e6ef28874126a0b384fd225ab83aa6d8a801c519194ce1" dependencies = [ "clap", ] @@ -2371,7 +2632,7 @@ dependencies = [ "hmac", "k256", "serde", - "sha2", + "sha2 0.10.9", "thiserror 1.0.69", ] @@ -2387,7 +2648,7 @@ dependencies = [ "once_cell", "pbkdf2 0.12.2", "rand 0.8.5", - "sha2", + "sha2 0.10.9", "thiserror 1.0.69", ] @@ -2405,7 +2666,7 @@ dependencies = [ "generic-array", "ripemd", "serde", - "sha2", + "sha2 0.10.9", "sha3", "thiserror 1.0.69", ] @@ -2848,6 +3109,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive-where" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e73f2692d4bd3cac41dca28934a39894200c9fabf49586d77d0e5954af1d7902" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "derive_arbitrary" version = "1.4.1" @@ -2961,7 +3233,7 @@ version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer", + "block-buffer 0.10.4", "const-oid", "crypto-common", "subtle", @@ -3048,6 +3320,18 @@ dependencies = [ "spki", ] +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "either" version = "1.15.0" @@ -3133,6 +3417,26 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "enum-ordinalize" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + [[package]] name = "enumn" version = "0.1.14" @@ -3221,7 +3525,7 @@ dependencies = [ "scrypt", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "sha3", "thiserror 1.0.69", "uuid 0.8.2", @@ -3445,6 +3749,7 @@ dependencies = [ "foundry-config", "foundry-debugger", "foundry-evm", + "foundry-evm-core", "foundry-linking", "foundry-solang-parser", "foundry-test-utils", @@ -3464,6 +3769,7 @@ dependencies = [ "rayon", "regex", "reqwest", + "revm", "semver 1.0.26", "serde", "serde_json", @@ -3522,7 +3828,7 @@ dependencies = [ "thiserror 2.0.12", "toml 0.8.22", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.19", ] [[package]] @@ -3619,12 +3925,13 @@ dependencies = [ "foundry-compilers", "foundry-config", "foundry-evm", + "foundry-evm-core", "foundry-test-utils", "futures", "itertools 0.14.0", "regex", "reqwest", - "revm-primitives", + "revm", "semver 1.0.26", "serde", "serde_json", @@ -3668,6 +3975,7 @@ dependencies = [ "alloy-chains", "alloy-consensus", "alloy-dyn-abi", + "alloy-evm", "alloy-genesis", "alloy-json-abi", "alloy-network", @@ -3758,7 +4066,7 @@ dependencies = [ "tikv-jemallocator", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.19", "tracing-tracy", "yansi", ] @@ -3833,7 +4141,7 @@ dependencies = [ "chrono", "comfy-table", "foundry-macros", - "revm-primitives", + "revm", "serde", "serde_json", "similar-asserts", @@ -3864,7 +4172,7 @@ dependencies = [ "semver 1.0.26", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "solar-parse", "solar-sema", "svm-rs", @@ -3873,7 +4181,7 @@ dependencies = [ "thiserror 2.0.12", "tokio", "tracing", - "winnow 0.7.9", + "winnow 0.7.10", "yansi", ] @@ -3969,7 +4277,7 @@ dependencies = [ "path-slash", "regex", "reqwest", - "revm-primitives", + "revm", "semver 1.0.26", "serde", "serde_json", @@ -4008,6 +4316,7 @@ name = "foundry-evm" version = "1.2.0" dependencies = [ "alloy-dyn-abi", + "alloy-evm", "alloy-json-abi", "alloy-primitives", "alloy-sol-types", @@ -4048,9 +4357,11 @@ version = "1.2.0" dependencies = [ "alloy-consensus", "alloy-dyn-abi", + "alloy-evm", "alloy-genesis", "alloy-json-abi", "alloy-network", + "alloy-op-evm", "alloy-primitives", "alloy-provider", "alloy-rpc-types", @@ -4065,6 +4376,7 @@ dependencies = [ "foundry-test-utils", "futures", "itertools 0.14.0", + "op-revm", "parking_lot", "revm", "revm-inspectors", @@ -4146,8 +4458,7 @@ dependencies = [ [[package]] name = "foundry-fork-db" version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba7beb856e73f59015823eb221a98b7c22b58bc4e7066c9c86774ebe74e61dd6" +source = "git+https://github.com/foundry-rs/foundry-fork-db?rev=811a61a#811a61a1312d6510447d5511f0e8714024813322" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -4220,7 +4531,7 @@ dependencies = [ "tempfile", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.19", ] [[package]] @@ -4760,9 +5071,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" dependencies = [ "atomic-waker", "bytes", @@ -4845,9 +5156,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hermit-abi" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" +checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08" [[package]] name = "hex" @@ -4858,6 +5169,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + [[package]] name = "hidapi-rusb" version = "1.3.3" @@ -5020,7 +5340,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -5317,7 +5637,7 @@ version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ - "hermit-abi 0.5.0", + "hermit-abi 0.5.1", "libc", "windows-sys 0.59.0", ] @@ -5372,9 +5692,9 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jiff" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd" +checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806" dependencies = [ "jiff-static", "jiff-tzdb-platform", @@ -5387,9 +5707,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300" +checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48" dependencies = [ "proc-macro2", "quote", @@ -5468,7 +5788,7 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2", + "sha2 0.10.9", "signature", ] @@ -5493,9 +5813,9 @@ dependencies = [ [[package]] name = "kqueue" -version = "1.0.8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" dependencies = [ "kqueue-sys", "libc", @@ -5557,9 +5877,6 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] [[package]] name = "lazycell" @@ -5595,9 +5912,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9627da5196e5d8ed0b0495e61e518847578da83483c37288316d9b2e03a7f72" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "libredox" @@ -5610,6 +5927,52 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "libsecp256k1" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79019718125edc905a079a70cfa5f3820bc76139fc91d6f9abc27ea2a887139" +dependencies = [ + "arrayref", + "base64 0.22.1", + "digest 0.9.0", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.8.5", + "serde", + "sha2 0.9.9", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" +dependencies = [ + "libsecp256k1-core", +] + [[package]] name = "libusb1-sys" version = "0.7.0" @@ -5663,7 +6026,7 @@ dependencies = [ "generator", "scoped-tls", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.19", ] [[package]] @@ -5752,9 +6115,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "mdbook" -version = "0.4.48" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6fbb4ac2d9fd7aa987c3510309ea3c80004a968d063c42f0d34fea070817c1" +checksum = "d1daacee059634081dee4250d2814763a365b92dfe14bfdef964bc27835209d4" dependencies = [ "ammonia", "anyhow", @@ -5773,7 +6136,7 @@ dependencies = [ "regex", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "shlex", "tempfile", "toml 0.5.11", @@ -6213,9 +6576,9 @@ dependencies = [ [[package]] name = "op-alloy-consensus" -version = "0.11.4" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "889facbf449b2d9c8de591cd467a6c7217936f3c1c07a281759c01c49d08d66d" +checksum = "917f7a65b83e8f9cf06d5209161babf39f5e5768e226a08ad42c033386248a66" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6229,9 +6592,9 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.11.4" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba7bfcc5d0b08c7a8bbdfaffa81e47edbb00185f0bf08e9f008216057700e50" +checksum = "57c087949da266a53e4c24d841a68590126ecfd3631b2fe74dbcd6da45702983" dependencies = [ "alloy-consensus", "alloy-eips", @@ -6245,6 +6608,23 @@ dependencies = [ "serde_json", ] +[[package]] +name = "op-revm" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "auto_impl", + "once_cell", + "revm", + "serde", +] + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "opener" version = "0.7.2" @@ -6296,7 +6676,7 @@ dependencies = [ "ecdsa", "elliptic-curve", "primeorder", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -6477,7 +6857,7 @@ checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" dependencies = [ "once_cell", "pest", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -6508,6 +6888,7 @@ checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", + "serde", ] [[package]] @@ -7260,31 +7641,131 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", + "webpki-roots 0.26.11", "windows-registry", ] [[package]] name = "revm" -version = "19.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c175ecec83bba464aa8406502fe5bf670491c2ace81a153264891d43bc7fa332" +version = "21.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "revm-bytecode", + "revm-context", + "revm-context-interface", + "revm-database", + "revm-database-interface", + "revm-handler", + "revm-inspector", + "revm-interpreter", + "revm-precompile", + "revm-primitives", + "revm-state", +] + +[[package]] +name = "revm-bytecode" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "bitvec", + "phf", + "revm-primitives", + "serde", +] + +[[package]] +name = "revm-context" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" dependencies = [ - "auto_impl", "cfg-if", - "dyn-clone", - "once_cell", + "derive-where", + "revm-bytecode", + "revm-context-interface", + "revm-database-interface", + "revm-primitives", + "revm-state", + "serde", +] + +[[package]] +name = "revm-context-interface" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "alloy-eip2930", + "alloy-eip7702", + "auto_impl", + "revm-database-interface", + "revm-primitives", + "revm-state", + "serde", +] + +[[package]] +name = "revm-database" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "alloy-eips", + "auto_impl", + "revm-bytecode", + "revm-database-interface", + "revm-primitives", + "revm-state", + "serde", +] + +[[package]] +name = "revm-database-interface" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "auto_impl", + "revm-primitives", + "revm-state", + "serde", +] + +[[package]] +name = "revm-handler" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "auto_impl", + "revm-bytecode", + "revm-context", + "revm-context-interface", + "revm-database-interface", "revm-interpreter", "revm-precompile", + "revm-primitives", + "revm-state", + "serde", +] + +[[package]] +name = "revm-inspector" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "auto_impl", + "revm-context", + "revm-database-interface", + "revm-handler", + "revm-interpreter", + "revm-primitives", + "revm-state", "serde", "serde_json", ] [[package]] name = "revm-inspectors" -version = "0.16.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a43423d81f4bef634469bfb2d9ebe36a9ea9167f20ab3a7d1ff1e05fa63099" +checksum = "8a32ec21c38a85f83773e6b3cdb7060aae8ac9edb291118fbfd4da7f2a50e620" dependencies = [ "alloy-primitives", "alloy-rpc-types-eth", @@ -7300,51 +7781,57 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "15.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcab7ef2064057acfc84731205f4bc77f4ec1b35630800b26ff6a185731c5ab" +version = "17.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" dependencies = [ + "revm-bytecode", + "revm-context-interface", "revm-primitives", "serde", ] [[package]] name = "revm-precompile" -version = "16.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99743c3a2cac341084cc15ac74286c4bf34a0941ebf60aa420cfdb9f81f72f9f" -dependencies = [ +version = "18.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "ark-bls12-381", + "ark-bn254", + "ark-ec", + "ark-ff 0.5.0", + "ark-serialize 0.5.0", "aurora-engine-modexp", "blst", "c-kzg", "cfg-if", "k256", + "libsecp256k1", "once_cell", "p256", "revm-primitives", "ripemd", "secp256k1", - "sha2", - "substrate-bn", + "sha2 0.10.9", ] [[package]] name = "revm-primitives" -version = "15.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f987564210317706def498421dfba2ae1af64a8edce82c6102758b48133fcb" +version = "17.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" dependencies = [ - "alloy-eip2930", - "alloy-eip7702", "alloy-primitives", - "auto_impl", - "bitflags 2.9.0", - "bitvec", - "c-kzg", - "cfg-if", - "dyn-clone", "enumn", - "hex", + "serde", +] + +[[package]] +name = "revm-state" +version = "2.0.0" +source = "git+https://github.com/bluealloy/revm.git?rev=2401c2c3#2401c2c37c515316817048b67f23bd10e77cd9d5" +dependencies = [ + "bitflags 2.9.0", + "revm-bytecode", + "revm-primitives", "serde", ] @@ -7538,9 +8025,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.26" +version = "0.23.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" dependencies = [ "aws-lc-rs", "log", @@ -7575,18 +8062,19 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" dependencies = [ "web-time", + "zeroize", ] [[package]] name = "rustls-webpki" -version = "0.103.1" +version = "0.103.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" +checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437" dependencies = [ "aws-lc-rs", "ring", @@ -7730,7 +8218,7 @@ dependencies = [ "hmac", "pbkdf2 0.11.0", "salsa20", - "sha2", + "sha2 0.10.9", ] [[package]] @@ -7756,10 +8244,11 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.29.1" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" dependencies = [ + "bitcoin_hashes", "rand 0.8.5", "secp256k1-sys", ] @@ -7994,6 +8483,19 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.9" @@ -8365,7 +8867,7 @@ dependencies = [ "semver 1.0.26", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "thiserror 2.0.12", "tokio", "toml_edit", @@ -8374,12 +8876,6 @@ dependencies = [ "zip-extract", ] -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - [[package]] name = "spki" version = "0.7.3" @@ -8492,19 +8988,6 @@ dependencies = [ "syn 2.0.101", ] -[[package]] -name = "substrate-bn" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" -dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand 0.8.5", - "rustc-hex", -] - [[package]] name = "subtle" version = "2.6.1" @@ -8602,7 +9085,7 @@ dependencies = [ "semver 1.0.26", "serde", "serde_json", - "sha2", + "sha2 0.10.9", "tempfile", "thiserror 2.0.12", "url", @@ -8902,9 +9385,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.44.2" +version = "1.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" dependencies = [ "backtrace", "bytes", @@ -8988,7 +9471,7 @@ dependencies = [ "tokio", "tokio-rustls", "tungstenite 0.26.2", - "webpki-roots", + "webpki-roots 0.26.11", ] [[package]] @@ -9046,7 +9529,7 @@ dependencies = [ "serde_spanned", "toml_datetime", "toml_write", - "winnow 0.7.9", + "winnow 0.7.10", ] [[package]] @@ -9219,7 +9702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" dependencies = [ "tracing", - "tracing-subscriber", + "tracing-subscriber 0.3.19", ] [[package]] @@ -9245,6 +9728,15 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "tracing-core", +] + [[package]] name = "tracing-subscriber" version = "0.3.19" @@ -9270,7 +9762,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eaa1852afa96e0fe9e44caa53dc0bd2d9d05e0f2611ce09f97f8677af56e4ba" dependencies = [ "tracing-core", - "tracing-subscriber", + "tracing-subscriber 0.3.19", "tracy-client", ] @@ -9857,9 +10349,9 @@ dependencies = [ [[package]] name = "web_atoms" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bcbdcad8fb2e316072ba6bbe09419afdb550285668ac2534f4230a6f2da0ee" +checksum = "0b9c5f0bc545ea3b20b423e33b9b457764de0b3730cd957f6c6aa6c301785f6e" dependencies = [ "phf", "phf_codegen", @@ -9869,9 +10361,18 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.10" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37493cadf42a2a939ed404698ded7fb378bf301b5011f973361779a3a74f8c93" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" dependencies = [ "rustls-pki-types", ] @@ -10238,9 +10739,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9fb597c990f03753e08d3c29efbfcf2019a003b4bf4ba19225c158e1549f0f3" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" dependencies = [ "memchr", ] @@ -10387,9 +10888,9 @@ dependencies = [ [[package]] name = "zip-extract" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3938d2b7d7ffd0fb7d4a86baeade9189535487d05d175401daf92306c531c0" +checksum = "db6d94e397dd6d0273e6747e46e7aa0289bfd9736ba8772f2fe948bc4adc3f73" dependencies = [ "log", "thiserror 2.0.12", diff --git a/Cargo.toml b/Cargo.toml index 96ff120cb30c8..fcf9b8e7c9a45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ resolver = "2" version = "1.2.0" edition = "2021" # Remember to update clippy.toml as well -rust-version = "1.83" +rust-version = "1.85" authors = ["Foundry Contributors"] license = "MIT OR Apache-2.0" homepage = "https://github.com/foundry-rs/foundry" @@ -116,10 +116,17 @@ alloy-sol-types.opt-level = 3 hashbrown.opt-level = 3 foldhash.opt-level = 3 keccak.opt-level = 3 +revm.opt-level = 3 +revm-primitives.opt-level = 3 revm-interpreter.opt-level = 3 revm-precompile.opt-level = 3 -revm-primitives.opt-level = 3 -revm.opt-level = 3 +revm-database-interface.opt-level = 3 +revm-database.opt-level = 3 +revm-bytecode.opt-level = 3 +revm-state.opt-level = 3 +revm-context-interface.opt-level = 3 +revm-context.opt-level = 3 +revm-inspector.opt-level = 3 ruint.opt-level = 3 sha2.opt-level = 3 sha3.opt-level = 3 @@ -196,32 +203,32 @@ solar-parse = { version = "=0.1.2", default-features = false } solar-sema = { version = "=0.1.2", default-features = false } ## revm -revm = { version = "19.4.0", default-features = false } -revm-primitives = { version = "15.1.0", default-features = false } -revm-inspectors = { version = "0.16.0", features = ["serde"] } +revm = { version = "21.0.0", default-features = false } +revm-inspectors = { version = "0.18.1", features = ["serde"] } +op-revm = { version = "2.0.0", default-features = false } ## alloy -alloy-consensus = { version = "0.12.1", default-features = false } -alloy-contract = { version = "0.12.1", default-features = false } -alloy-eips = { version = "0.12.1", default-features = false } -alloy-genesis = { version = "0.12.1", default-features = false } -alloy-json-rpc = { version = "0.12.1", default-features = false } -alloy-network = { version = "0.12.1", default-features = false } -alloy-provider = { version = "0.12.1", default-features = false } -alloy-pubsub = { version = "0.12.1", default-features = false } -alloy-rpc-client = { version = "0.12.1", default-features = false } -alloy-rpc-types = { version = "0.12.1", default-features = true } -alloy-serde = { version = "0.12.1", default-features = false } -alloy-signer = { version = "0.12.1", default-features = false } -alloy-signer-aws = { version = "0.12.1", default-features = false } -alloy-signer-gcp = { version = "0.12.1", default-features = false } -alloy-signer-ledger = { version = "0.12.1", default-features = false } -alloy-signer-local = { version = "0.12.1", default-features = false } -alloy-signer-trezor = { version = "0.12.1", default-features = false } -alloy-transport = { version = "0.12.1", default-features = false } -alloy-transport-http = { version = "0.12.1", default-features = false } -alloy-transport-ipc = { version = "0.12.1", default-features = false } -alloy-transport-ws = { version = "0.12.1", default-features = false } +alloy-consensus = { version = "0.13.0", default-features = false } +alloy-contract = { version = "0.13.0", default-features = false } +alloy-eips = { version = "0.13.0", default-features = false } +alloy-genesis = { version = "0.13.0", default-features = false } +alloy-json-rpc = { version = "0.13.0", default-features = false } +alloy-network = { version = "0.13.0", default-features = false } +alloy-provider = { version = "0.13.0", default-features = false } +alloy-pubsub = { version = "0.13.0", default-features = false } +alloy-rpc-client = { version = "0.13.0", default-features = false } +alloy-rpc-types = { version = "0.13.0", default-features = true } +alloy-serde = { version = "0.13.0", default-features = false } +alloy-signer = { version = "0.13.0", default-features = false } +alloy-signer-aws = { version = "0.13.0", default-features = false } +alloy-signer-gcp = { version = "0.13.0", default-features = false } +alloy-signer-ledger = { version = "0.13.0", default-features = false } +alloy-signer-local = { version = "0.13.0", default-features = false } +alloy-signer-trezor = { version = "0.13.0", default-features = false } +alloy-transport = { version = "0.13.0", default-features = false } +alloy-transport-http = { version = "0.13.0", default-features = false } +alloy-transport-ipc = { version = "0.13.0", default-features = false } +alloy-transport-ws = { version = "0.13.0", default-features = false } ## alloy-core alloy-dyn-abi = "0.8.22" @@ -237,12 +244,14 @@ alloy-sol-macro-input = "0.8.22" alloy-sol-types = "0.8.22" alloy-chains = "0.1" +alloy-evm = "0.3.2" +alloy-op-evm = "0.3.2" alloy-rlp = "0.3" alloy-trie = "0.7.0" ## op-alloy -op-alloy-consensus = "0.11.0" -op-alloy-rpc-types = "0.11.0" +op-alloy-consensus = "0.12.0" +op-alloy-rpc-types = "0.12.0" ## cli anstream = "0.6" @@ -359,3 +368,11 @@ idna_adapter = "=1.1.0" # alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ipc = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } # alloy-transport-ws = { git = "https://github.com/alloy-rs/alloy", rev = "7fab7ee" } + +## revm +revm = { git = "https://github.com/bluealloy/revm.git", rev = "2401c2c3" } +op-revm = { git = "https://github.com/bluealloy/revm.git", rev = "2401c2c3" } +# revm-inspectors = { git = "https://github.com/paradigmxyz/revm-inspectors.git", rev = "a625c04" } + +## foundry +foundry-fork-db = { git = "https://github.com/foundry-rs/foundry-fork-db", rev = "811a61a" } diff --git a/clippy.toml b/clippy.toml index 69dfa469ce10b..86b7412b14a56 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,4 +1,4 @@ -msrv = "1.83" +msrv = "1.85" # `bytes::Bytes` is included by default and `alloy_primitives::Bytes` is a wrapper around it, # so it is safe to ignore it as well. diff --git a/crates/anvil/Cargo.toml b/crates/anvil/Cargo.toml index 777026f038c0e..c70d1eb82c592 100644 --- a/crates/anvil/Cargo.toml +++ b/crates/anvil/Cargo.toml @@ -27,15 +27,11 @@ foundry-cli.workspace = true foundry-common.workspace = true foundry-config.workspace = true foundry-evm.workspace = true +foundry-evm-core.workspace = true -# evm support -revm = { workspace = true, features = [ - "std", - "serde", - "memory_limit", - "c-kzg", -] } -revm-inspectors.workspace = true +# alloy +alloy-evm.workspace = true +alloy-op-evm.workspace = true alloy-primitives = { workspace = true, features = ["serde"] } alloy-consensus = { workspace = true, features = ["k256", "kzg"] } alloy-contract = { workspace = true, features = ["pubsub"] } @@ -61,6 +57,16 @@ alloy-genesis.workspace = true alloy-trie.workspace = true op-alloy-consensus = { workspace = true, features = ["serde"] } +# revm +revm = { workspace = true, features = [ + "std", + "serde", + "memory_limit", + "c-kzg", +] } +revm-inspectors.workspace = true +op-revm.workspace = true + # axum related axum.workspace = true hyper.workspace = true diff --git a/crates/anvil/core/Cargo.toml b/crates/anvil/core/Cargo.toml index f7428d356bf53..0b64c630bda9b 100644 --- a/crates/anvil/core/Cargo.toml +++ b/crates/anvil/core/Cargo.toml @@ -21,6 +21,7 @@ revm = { workspace = true, default-features = false, features = [ "memory_limit", "c-kzg", ] } +op-revm.workspace = true alloy-primitives = { workspace = true, features = ["serde", "rlp"] } alloy-rpc-types = { workspace = true, features = ["anvil", "trace"] } diff --git a/crates/anvil/core/src/eth/transaction/mod.rs b/crates/anvil/core/src/eth/transaction/mod.rs index e04a3afb09c36..85bba5504d9a0 100644 --- a/crates/anvil/core/src/eth/transaction/mod.rs +++ b/crates/anvil/core/src/eth/transaction/mod.rs @@ -23,10 +23,8 @@ use alloy_serde::{OtherFields, WithOtherFields}; use bytes::BufMut; use foundry_evm::traces::CallTraceNode; use op_alloy_consensus::{TxDeposit, DEPOSIT_TX_TYPE_ID}; -use revm::{ - interpreter::InstructionResult, - primitives::{OptimismFields, TxEnv}, -}; +use op_revm::{transaction::deposit::DepositTransactionParts, OpTransaction}; +use revm::{context::TxEnv, interpreter::InstructionResult}; use serde::{Deserialize, Serialize}; use std::ops::{Deref, Mul}; @@ -180,7 +178,7 @@ pub fn transaction_request_to_typed( } } -fn has_optimism_fields(other: &OtherFields) -> bool { +pub fn has_optimism_fields(other: &OtherFields) -> bool { other.contains_key("sourceHash") && other.contains_key("mint") && other.contains_key("isSystemTx") @@ -403,7 +401,9 @@ impl PendingTransaction { /// Converts the [PendingTransaction] into the [TxEnv] context that [`revm`](foundry_evm) /// expects. - pub fn to_revm_tx_env(&self) -> TxEnv { + /// + /// Base [`TxEnv`] is encapsulated in the [`op_revm::OpTransaction`] + pub fn to_revm_tx_env(&self) -> OpTransaction { fn transact_to(kind: &TxKind) -> TxKind { match kind { TxKind::Call(c) => TxKind::Call(*c), @@ -416,19 +416,20 @@ impl PendingTransaction { TypedTransaction::Legacy(tx) => { let chain_id = tx.tx().chain_id; let TxLegacy { nonce, gas_price, gas_limit, value, to, input, .. } = tx.tx(); - TxEnv { + OpTransaction::new(TxEnv { caller, - transact_to: transact_to(to), + kind: transact_to(to), data: input.clone(), chain_id, - nonce: Some(*nonce), + nonce: *nonce, value: (*value), - gas_price: U256::from(*gas_price), + gas_price: *gas_price, gas_priority_fee: None, gas_limit: *gas_limit, - access_list: vec![], + access_list: vec![].into(), + tx_type: 0, ..Default::default() - } + }) } TypedTransaction::EIP2930(tx) => { let TxEip2930 { @@ -442,19 +443,20 @@ impl PendingTransaction { access_list, .. } = tx.tx(); - TxEnv { + OpTransaction::new(TxEnv { caller, - transact_to: transact_to(to), + kind: transact_to(to), data: input.clone(), chain_id: Some(*chain_id), - nonce: Some(*nonce), + nonce: *nonce, value: *value, - gas_price: U256::from(*gas_price), + gas_price: *gas_price, gas_priority_fee: None, gas_limit: *gas_limit, - access_list: access_list.clone().into(), + access_list: access_list.clone(), + tx_type: 1, ..Default::default() - } + }) } TypedTransaction::EIP1559(tx) => { let TxEip1559 { @@ -469,19 +471,20 @@ impl PendingTransaction { access_list, .. } = tx.tx(); - TxEnv { + OpTransaction::new(TxEnv { caller, - transact_to: transact_to(to), + kind: transact_to(to), data: input.clone(), chain_id: Some(*chain_id), - nonce: Some(*nonce), + nonce: *nonce, value: *value, - gas_price: U256::from(*max_fee_per_gas), - gas_priority_fee: Some(U256::from(*max_priority_fee_per_gas)), + gas_price: *max_fee_per_gas, + gas_priority_fee: Some(*max_priority_fee_per_gas), gas_limit: *gas_limit, - access_list: access_list.clone().into(), + access_list: access_list.clone(), + tx_type: 2, ..Default::default() - } + }) } TypedTransaction::EIP4844(tx) => { let TxEip4844 { @@ -498,21 +501,22 @@ impl PendingTransaction { blob_versioned_hashes, .. } = tx.tx().tx(); - TxEnv { + OpTransaction::new(TxEnv { caller, - transact_to: TxKind::Call(*to), + kind: TxKind::Call(*to), data: input.clone(), chain_id: Some(*chain_id), - nonce: Some(*nonce), + nonce: *nonce, value: *value, - gas_price: U256::from(*max_fee_per_gas), - gas_priority_fee: Some(U256::from(*max_priority_fee_per_gas)), - max_fee_per_blob_gas: Some(U256::from(*max_fee_per_blob_gas)), + gas_price: *max_fee_per_gas, + gas_priority_fee: Some(*max_priority_fee_per_gas), + max_fee_per_blob_gas: *max_fee_per_blob_gas, blob_hashes: blob_versioned_hashes.clone(), gas_limit: *gas_limit, - access_list: access_list.clone().into(), + access_list: access_list.clone(), + tx_type: 3, ..Default::default() - } + }) } TypedTransaction::EIP7702(tx) => { let TxEip7702 { @@ -527,20 +531,21 @@ impl PendingTransaction { authorization_list, input, } = tx.tx(); - TxEnv { + OpTransaction::new(TxEnv { caller, - transact_to: TxKind::Call(*to), + kind: TxKind::Call(*to), data: input.clone(), chain_id: Some(*chain_id), - nonce: Some(*nonce), + nonce: *nonce, value: *value, - gas_price: U256::from(*max_fee_per_gas), - gas_priority_fee: Some(U256::from(*max_priority_fee_per_gas)), + gas_price: *max_fee_per_gas, + gas_priority_fee: Some(*max_priority_fee_per_gas), gas_limit: *gas_limit, - access_list: access_list.clone().into(), - authorization_list: Some(authorization_list.clone().into()), + access_list: access_list.clone(), + authorization_list: authorization_list.clone(), + tx_type: 4, ..Default::default() - } + }) } TypedTransaction::Deposit(tx) => { let chain_id = tx.chain_id(); @@ -555,25 +560,29 @@ impl PendingTransaction { is_system_tx, .. } = tx; - TxEnv { + + let base = TxEnv { caller, - transact_to: transact_to(kind), + kind: transact_to(kind), data: input.clone(), chain_id, - nonce: Some(*nonce), + nonce: *nonce, value: *value, - gas_price: U256::ZERO, + gas_price: 0, gas_priority_fee: None, gas_limit: { *gas_limit }, - access_list: vec![], - optimism: OptimismFields { - source_hash: Some(*source_hash), - mint: Some(mint.to::()), - is_system_transaction: Some(*is_system_tx), - enveloped_tx: None, - }, + access_list: vec![].into(), + tx_type: DEPOSIT_TX_TYPE_ID, ..Default::default() - } + }; + + let deposit = DepositTransactionParts { + source_hash: *source_hash, + mint: Some(mint.to::()), + is_system_transaction: *is_system_tx, + }; + + OpTransaction { base, deposit, enveloped_tx: None } } } } diff --git a/crates/anvil/src/cmd.rs b/crates/anvil/src/cmd.rs index 4b89f0a6dfb89..2968b12739786 100644 --- a/crates/anvil/src/cmd.rs +++ b/crates/anvil/src/cmd.rs @@ -1,8 +1,7 @@ use crate::{ config::{ForkChoice, DEFAULT_MNEMONIC}, eth::{backend::db::SerializableState, pool::transactions::TransactionOrder, EthApi}, - hardfork::OptimismHardfork, - AccountGenerator, EthereumHardfork, NodeConfig, CHAIN_ID, + AccountGenerator, EthereumHardfork, NodeConfig, OptimismHardfork, CHAIN_ID, }; use alloy_genesis::Genesis; use alloy_primitives::{utils::Unit, B256, U256}; @@ -521,7 +520,7 @@ pub struct AnvilEvmArgs { /// The block gas limit. #[arg(long, alias = "block-gas-limit", help_heading = "Environment config")] - pub gas_limit: Option, + pub gas_limit: Option, /// Disable the `call.gas_limit <= block.gas_limit` constraint. #[arg( @@ -792,9 +791,8 @@ fn duration_from_secs_f64(s: &str) -> Result { #[cfg(test)] mod tests { - use crate::EthereumHardfork; - use super::*; + use crate::{EthereumHardfork, OptimismHardfork}; use std::{env, net::Ipv4Addr}; #[test] diff --git a/crates/anvil/src/config.rs b/crates/anvil/src/config.rs index f9606eeeb08fd..097618ecf8afa 100644 --- a/crates/anvil/src/config.rs +++ b/crates/anvil/src/config.rs @@ -2,6 +2,7 @@ use crate::{ eth::{ backend::{ db::{Db, SerializableState}, + env::Env, fork::{ClientFork, ClientForkConfig}, genesis::GenesisConfig, mem::fork_db::ForkedDatabase, @@ -10,9 +11,9 @@ use crate::{ fees::{INITIAL_BASE_FEE, INITIAL_GAS_PRICE}, pool::transactions::{PoolTransaction, TransactionOrder}, }, - hardfork::{ChainHardfork, OptimismHardfork}, + hardfork::ChainHardfork, mem::{self, in_memory_db::MemDb}, - EthereumHardfork, FeeManager, PrecompileFactory, + EthereumHardfork, FeeManager, OptimismHardfork, PrecompileFactory, }; use alloy_consensus::BlockHeader; use alloy_genesis::Genesis; @@ -36,13 +37,18 @@ use foundry_config::Config; use foundry_evm::{ backend::{BlockchainDb, BlockchainDbMeta, SharedBackend}, constants::DEFAULT_CREATE2_DEPLOYER, - revm::primitives::{BlockEnv, CfgEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, SpecId, TxEnv}, utils::apply_chain_and_block_specific_env_changes, }; +use foundry_evm_core::AsEnvMut; use itertools::Itertools; +use op_revm::OpTransaction; use parking_lot::RwLock; use rand::thread_rng; -use revm::primitives::BlobExcessGasAndPrice; +use revm::{ + context::{BlockEnv, CfgEnv, TxEnv}, + context_interface::block::BlobExcessGasAndPrice, + primitives::hardfork::SpecId, +}; use serde_json::{json, Value}; use std::{ fmt::Write as FmtWrite, @@ -63,7 +69,7 @@ pub const NODE_PORT: u16 = 8545; /// Default chain id of the node pub const CHAIN_ID: u64 = 31337; /// The default gas limit for all transactions -pub const DEFAULT_GAS_LIMIT: u128 = 30_000_000; +pub const DEFAULT_GAS_LIMIT: u64 = 30_000_000; /// Default mnemonic for dev accounts pub const DEFAULT_MNEMONIC: &str = "test test test test test test test test test test test junk"; @@ -86,7 +92,7 @@ pub struct NodeConfig { /// Chain ID of the EVM chain pub chain_id: Option, /// Default gas limit for all txs - pub gas_limit: Option, + pub gas_limit: Option, /// If set to `true`, disables the block gas limit pub disable_block_gas_limit: bool, /// Default gas price for all txs @@ -505,7 +511,7 @@ impl NodeConfig { pub fn get_blob_excess_gas_and_price(&self) -> BlobExcessGasAndPrice { if let Some(blob_excess_gas_and_price) = &self.blob_excess_gas_and_price { - blob_excess_gas_and_price.clone() + *blob_excess_gas_and_price } else if let Some(excess_blob_gas) = self.genesis.as_ref().and_then(|g| g.excess_blob_gas) { BlobExcessGasAndPrice::new(excess_blob_gas, false) @@ -587,7 +593,7 @@ impl NodeConfig { /// Sets the gas limit #[must_use] - pub fn with_gas_limit(mut self, gas_limit: Option) -> Self { + pub fn with_gas_limit(mut self, gas_limit: Option) -> Self { self.gas_limit = gas_limit; self } @@ -1018,8 +1024,9 @@ impl NodeConfig { pub(crate) async fn setup(&mut self) -> Result { // configure the revm environment - let mut cfg = - CfgEnvWithHandlerCfg::new_with_spec_id(CfgEnv::default(), self.get_hardfork().into()); + let mut cfg = CfgEnv::default(); + cfg.spec = self.get_hardfork().into(); + cfg.chain_id = self.get_chain_id(); cfg.limit_contract_code_size = self.code_size_limit; // EIP-3607 rejects transactions from senders with deployed code. @@ -1027,25 +1034,28 @@ impl NodeConfig { // caller is a contract. So we disable the check by default. cfg.disable_eip3607 = true; cfg.disable_block_gas_limit = self.disable_block_gas_limit; - cfg.handler_cfg.is_optimism = self.enable_optimism; if let Some(value) = self.memory_limit { cfg.memory_limit = value; } - let env = revm::primitives::Env { - cfg: cfg.cfg_env, - block: BlockEnv { - gas_limit: U256::from(self.gas_limit()), - basefee: U256::from(self.get_base_fee()), + let spec_id = cfg.spec; + let mut env = Env::new( + cfg, + BlockEnv { + gas_limit: self.gas_limit(), + basefee: self.get_base_fee(), ..Default::default() }, - tx: TxEnv { chain_id: self.get_chain_id().into(), ..Default::default() }, - }; - let mut env = EnvWithHandlerCfg::new(Box::new(env), cfg.handler_cfg); + OpTransaction { + base: TxEnv { chain_id: Some(self.get_chain_id()), ..Default::default() }, + ..Default::default() + }, + self.enable_optimism, + ); let fees = FeeManager::new( - cfg.handler_cfg.spec_id, + spec_id, self.get_base_fee(), !self.disable_min_priority_fee, self.get_gas_price(), @@ -1064,16 +1074,16 @@ impl NodeConfig { // --chain-id flag gets precedence over the genesis.json chain id // if self.chain_id.is_none() { - env.cfg.chain_id = genesis.config.chain_id; + env.evm_env.cfg_env.chain_id = genesis.config.chain_id; } - env.block.timestamp = U256::from(genesis.timestamp); + env.evm_env.block_env.timestamp = genesis.timestamp; if let Some(base_fee) = genesis.base_fee_per_gas { - env.block.basefee = U256::from(base_fee); + env.evm_env.block_env.basefee = base_fee.try_into()?; } if let Some(number) = genesis.number { - env.block.number = U256::from(number); + env.evm_env.block_env.number = number; } - env.block.coinbase = genesis.coinbase; + env.evm_env.block_env.beneficiary = genesis.coinbase; } let genesis = GenesisConfig { @@ -1129,7 +1139,7 @@ impl NodeConfig { pub async fn setup_fork_db( &mut self, eth_rpc_url: String, - env: &mut EnvWithHandlerCfg, + env: &mut Env, fees: &FeeManager, ) -> Result<(Arc>>, Option)> { let (db, config) = self.setup_fork_db_config(eth_rpc_url, env, fees).await?; @@ -1146,7 +1156,7 @@ impl NodeConfig { pub async fn setup_fork_db_config( &mut self, eth_rpc_url: String, - env: &mut EnvWithHandlerCfg, + env: &mut Env, fees: &FeeManager, ) -> Result<(ForkedDatabase, ClientForkConfig)> { debug!(target: "node", ?eth_rpc_url, "setting up fork db"); @@ -1177,7 +1187,7 @@ impl NodeConfig { provider.get_chain_id().await.wrap_err("failed to fetch network chain ID")?; if alloy_chains::NamedChain::Mainnet == chain_id { let hardfork: EthereumHardfork = fork_block_number.into(); - env.handler_cfg.spec_id = hardfork.into(); + env.evm_env.cfg_env.spec = hardfork.into(); self.hardfork = Some(ChainHardfork::Ethereum(hardfork)); } Some(U256::from(chain_id)) @@ -1221,16 +1231,16 @@ latest block number: {latest_block}" let gas_limit = self.fork_gas_limit(&block); self.gas_limit = Some(gas_limit); - env.block = BlockEnv { - number: U256::from(fork_block_number), - timestamp: U256::from(block.header.timestamp), + env.evm_env.block_env = BlockEnv { + number: fork_block_number, + timestamp: block.header.timestamp, difficulty: block.header.difficulty, // ensures prevrandao is set prevrandao: Some(block.header.mix_hash.unwrap_or_default()), - gas_limit: U256::from(gas_limit), + gas_limit, // Keep previous `coinbase` and `basefee` value - coinbase: env.block.coinbase, - basefee: env.block.basefee, + beneficiary: env.evm_env.block_env.beneficiary, + basefee: env.evm_env.block_env.basefee, ..Default::default() }; @@ -1238,11 +1248,11 @@ latest block number: {latest_block}" if self.base_fee.is_none() { if let Some(base_fee) = block.header.base_fee_per_gas { self.base_fee = Some(base_fee); - env.block.basefee = U256::from(base_fee); + env.evm_env.block_env.basefee = base_fee; // this is the base fee of the current block, but we need the base fee of // the next block let next_block_base_fee = fees.get_next_block_base_fee_per_gas( - block.header.gas_used as u128, + block.header.gas_used, gas_limit, block.header.base_fee_per_gas.unwrap_or_default(), ); @@ -1253,10 +1263,10 @@ latest block number: {latest_block}" if let (Some(blob_excess_gas), Some(blob_gas_used)) = (block.header.excess_blob_gas, block.header.blob_gas_used) { - env.block.blob_excess_gas_and_price = + env.evm_env.block_env.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(blob_excess_gas, false)); - let next_block_blob_excess_gas = fees - .get_next_block_blob_excess_gas(blob_excess_gas as u128, blob_gas_used as u128); + let next_block_blob_excess_gas = + fees.get_next_block_blob_excess_gas(blob_excess_gas, blob_gas_used); fees.set_blob_excess_gas_and_price(BlobExcessGasAndPrice::new( next_block_blob_excess_gas, false, @@ -1285,15 +1295,15 @@ latest block number: {latest_block}" // need to update the dev signers and env with the chain id self.set_chain_id(Some(chain_id)); - env.cfg.chain_id = chain_id; - env.tx.chain_id = chain_id.into(); + env.evm_env.cfg_env.chain_id = chain_id; + env.tx.base.chain_id = chain_id.into(); chain_id }; let override_chain_id = self.chain_id; // apply changes such as difficulty -> prevrandao and chain specifics for current chain id - apply_chain_and_block_specific_env_changes::(env, &block); + apply_chain_and_block_specific_env_changes::(env.as_env_mut(), &block); - let meta = BlockchainDbMeta::new(*env.env.clone(), eth_rpc_url.clone()); + let meta = BlockchainDbMeta::new(env.evm_env.block_env.clone(), eth_rpc_url.clone()); let block_chain_db = if self.fork_chain_id.is_some() { BlockchainDb::new_skip_check(meta, self.block_cache_path(fork_block_number)) } else { @@ -1324,7 +1334,7 @@ latest block number: {latest_block}" compute_units_per_second: self.compute_units_per_second, total_difficulty: block.header.total_difficulty.unwrap_or_default(), blob_gas_used: block.header.blob_gas_used.map(|g| g as u128), - blob_excess_gas_and_price: env.block.blob_excess_gas_and_price.clone(), + blob_excess_gas_and_price: env.evm_env.block_env.blob_excess_gas_and_price, force_transactions, }; @@ -1344,24 +1354,24 @@ latest block number: {latest_block}" pub(crate) fn fork_gas_limit( &self, block: &Block, - ) -> u128 { + ) -> u64 { if !self.disable_block_gas_limit { if let Some(gas_limit) = self.gas_limit { return gas_limit; } else if block.header.gas_limit() > 0 { - return block.header.gas_limit() as u128; + return block.header.gas_limit(); } } - u64::MAX as u128 + u64::MAX } /// Returns the gas limit for a non forked anvil instance /// /// Checks the config for the `disable_block_gas_limit` flag - pub(crate) fn gas_limit(&self) -> u128 { + pub(crate) fn gas_limit(&self) -> u64 { if self.disable_block_gas_limit { - return u64::MAX as u128; + return u64::MAX; } self.gas_limit.unwrap_or(DEFAULT_GAS_LIMIT) @@ -1380,7 +1390,7 @@ async fn derive_block_and_transactions( ForkChoice::Block(block_number) => { let block_number = *block_number; if block_number >= 0 { - return Ok((block_number as u64, None)) + return Ok((block_number as u64, None)); } // subtract from latest block number let latest = provider.get_block_number().await?; diff --git a/crates/anvil/src/eth/api.rs b/crates/anvil/src/eth/api.rs index dc6e78bb6fedb..670ef2d091c08 100644 --- a/crates/anvil/src/eth/api.rs +++ b/crates/anvil/src/eth/api.rs @@ -27,7 +27,6 @@ use crate::{ }, filter::{EthFilter, Filters, LogsFilter}, mem::transaction_build, - revm::primitives::{BlobExcessGasAndPrice, Output}, ClientFork, LoggingManager, Miner, MiningMode, StorageInfo, }; use alloy_consensus::{ @@ -80,21 +79,20 @@ use anvil_core::{ }; use anvil_rpc::{error::RpcError, response::ResponseResult}; use foundry_common::provider::ProviderBuilder; -use foundry_evm::{ - backend::DatabaseError, - decode::RevertDecoder, - revm::{ - db::DatabaseRef, - interpreter::{return_ok, return_revert, InstructionResult}, - primitives::BlockEnv, - }, -}; +use foundry_evm::{backend::DatabaseError, decode::RevertDecoder}; use futures::{ channel::{mpsc::Receiver, oneshot}, StreamExt, }; use parking_lot::RwLock; -use revm::primitives::{eip7702::PER_EMPTY_ACCOUNT_COST, Bytecode}; +use revm::{ + bytecode::Bytecode, + context::BlockEnv, + context_interface::{block::BlobExcessGasAndPrice, result::Output}, + database::DatabaseRef, + interpreter::{return_ok, return_revert, InstructionResult}, + primitives::eip7702::PER_EMPTY_ACCOUNT_COST, +}; use std::{future::Future, sync::Arc, time::Duration}; use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver}; @@ -1965,11 +1963,11 @@ impl EthApi { let env = self.backend.env().read(); let fork_config = self.backend.get_fork(); let tx_order = self.transaction_order.read(); - let hard_fork: &str = env.handler_cfg.spec_id.into(); + let hard_fork: &str = env.evm_env.cfg_env.spec.into(); Ok(NodeInfo { current_block_number: self.backend.best_number(), - current_block_timestamp: env.block.timestamp.try_into().unwrap_or(u64::MAX), + current_block_timestamp: env.evm_env.block_env.timestamp, current_block_hash: self.backend.best_hash(), hard_fork: hard_fork.to_string(), transaction_order: match *tx_order { @@ -2327,7 +2325,7 @@ impl EthApi { /// Sets the reported block number /// /// Handler for ETH RPC call: `anvil_setBlock` - pub fn anvil_set_block(&self, block_number: U256) -> Result<()> { + pub fn anvil_set_block(&self, block_number: u64) -> Result<()> { node_info!("anvil_setBlock"); self.backend.set_block_number(block_number); Ok(()) @@ -2753,8 +2751,7 @@ impl EthApi { // get the highest possible gas limit, either the request's set value or the currently // configured gas limit - let mut highest_gas_limit = - request.gas.map_or(block_env.gas_limit.to::(), |g| g as u128); + let mut highest_gas_limit = request.gas.map_or(block_env.gas_limit.into(), |g| g as u128); let gas_price = fees.gas_price.unwrap_or_default(); // If we have non-zero gas price, cap gas limit by sender balance @@ -3256,7 +3253,8 @@ impl TryFrom, u128, State)>> for GasEs InstructionResult::MemoryOOG | InstructionResult::MemoryLimitOOG | InstructionResult::PrecompileOOG | - InstructionResult::InvalidOperandOOG => Ok(Self::OutOfGas), + InstructionResult::InvalidOperandOOG | + InstructionResult::ReentrancySentryOOG => Ok(Self::OutOfGas), InstructionResult::OpcodeNotFound | InstructionResult::CallNotAllowedInsideStatic | @@ -3283,7 +3281,7 @@ impl TryFrom, u128, State)>> for GasEs // Handle Revm EOF InstructionResults: Not supported yet InstructionResult::ReturnContractInNotInitEOF | InstructionResult::EOFOpcodeDisabledInLegacy | - InstructionResult::EOFFunctionStackOverflow | + InstructionResult::SubRoutineStackOverflow | InstructionResult::CreateInitCodeStartingEF00 | InstructionResult::InvalidEOFInitCode | InstructionResult::EofAuxDataOverflow | diff --git a/crates/anvil/src/eth/backend/db.rs b/crates/anvil/src/eth/backend/db.rs index ecf1759e63a52..e39baee9193df 100644 --- a/crates/anvil/src/eth/backend/db.rs +++ b/crates/anvil/src/eth/backend/db.rs @@ -1,24 +1,24 @@ //! Helper types for working with [revm](foundry_evm::revm) -use crate::{mem::storage::MinedTransaction, revm::primitives::AccountInfo}; +use crate::mem::storage::MinedTransaction; use alloy_consensus::Header; -use alloy_primitives::{keccak256, Address, Bytes, B256, U256, U64}; +use alloy_primitives::{keccak256, map::HashMap, Address, Bytes, B256, U256}; use alloy_rpc_types::BlockId; use anvil_core::eth::{ block::Block, transaction::{MaybeImpersonatedTransaction, TransactionInfo, TypedReceipt, TypedTransaction}, }; use foundry_common::errors::FsPathError; -use foundry_evm::{ - backend::{ - BlockchainDb, DatabaseError, DatabaseResult, MemDb, RevertStateSnapshotAction, - StateSnapshot, - }, - revm::{ - db::{CacheDB, DatabaseRef, DbAccount}, - primitives::{BlockEnv, Bytecode, HashMap, KECCAK_EMPTY}, - Database, DatabaseCommit, - }, +use foundry_evm::backend::{ + BlockchainDb, DatabaseError, DatabaseResult, MemDb, RevertStateSnapshotAction, StateSnapshot, +}; +use revm::{ + bytecode::Bytecode, + context::BlockEnv, + database::{CacheDB, DatabaseRef, DbAccount}, + primitives::KECCAK_EMPTY, + state::AccountInfo, + Database, DatabaseCommit, }; use serde::{ de::{MapAccess, Visitor}, @@ -139,7 +139,7 @@ pub trait Db: fn dump_state( &self, at: BlockEnv, - best_number: U64, + best_number: u64, blocks: Vec, transactions: Vec, historical_states: Option, @@ -215,13 +215,13 @@ impl + Send + Sync + Clone + fmt::Debug> D } fn insert_block_hash(&mut self, number: U256, hash: B256) { - self.block_hashes.insert(number, hash); + self.cache.block_hashes.insert(number, hash); } fn dump_state( &self, _at: BlockEnv, - _best_number: U64, + _best_number: u64, _blocks: Vec, _transaction: Vec, _historical_states: Option, @@ -248,37 +248,37 @@ impl> MaybeFullDatabase for CacheDB { } fn maybe_as_full_db(&self) -> Option<&HashMap> { - Some(&self.accounts) + Some(&self.cache.accounts) } fn clear_into_state_snapshot(&mut self) -> StateSnapshot { - let db_accounts = std::mem::take(&mut self.accounts); + let db_accounts = std::mem::take(&mut self.cache.accounts); let mut accounts = HashMap::default(); let mut account_storage = HashMap::default(); for (addr, mut acc) in db_accounts { account_storage.insert(addr, std::mem::take(&mut acc.storage)); let mut info = acc.info; - info.code = self.contracts.remove(&info.code_hash); + info.code = self.cache.contracts.remove(&info.code_hash); accounts.insert(addr, info); } - let block_hashes = std::mem::take(&mut self.block_hashes); + let block_hashes = std::mem::take(&mut self.cache.block_hashes); StateSnapshot { accounts, storage: account_storage, block_hashes } } fn read_as_state_snapshot(&self) -> StateSnapshot { - let db_accounts = self.accounts.clone(); + let db_accounts = self.cache.accounts.clone(); let mut accounts = HashMap::default(); let mut account_storage = HashMap::default(); for (addr, acc) in db_accounts { account_storage.insert(addr, acc.storage.clone()); let mut info = acc.info; - info.code = self.contracts.get(&info.code_hash).cloned(); + info.code = self.cache.contracts.get(&info.code_hash).cloned(); accounts.insert(addr, info); } - let block_hashes = self.block_hashes.clone(); + let block_hashes = self.cache.block_hashes.clone(); StateSnapshot { accounts, storage: account_storage, block_hashes } } @@ -291,9 +291,9 @@ impl> MaybeFullDatabase for CacheDB { for (addr, mut acc) in accounts { if let Some(code) = acc.code.take() { - self.contracts.insert(acc.code_hash, code); + self.cache.contracts.insert(acc.code_hash, code); } - self.accounts.insert( + self.cache.accounts.insert( addr, DbAccount { info: acc, @@ -302,7 +302,7 @@ impl> MaybeFullDatabase for CacheDB { }, ); } - self.block_hashes = block_hashes; + self.cache.block_hashes = block_hashes; } } @@ -388,7 +388,7 @@ pub struct SerializableState { pub block: Option, pub accounts: BTreeMap, /// The best block number of the state, can be different from block number (Arbitrum chain). - pub best_block_number: Option, + pub best_block_number: Option, #[serde(default)] pub blocks: Vec, #[serde(default)] diff --git a/crates/anvil/src/eth/backend/env.rs b/crates/anvil/src/eth/backend/env.rs new file mode 100644 index 0000000000000..d4b8de797023d --- /dev/null +++ b/crates/anvil/src/eth/backend/env.rs @@ -0,0 +1,30 @@ +use alloy_evm::EvmEnv; +use foundry_evm::EnvMut; +use foundry_evm_core::AsEnvMut; +use op_revm::OpTransaction; +use revm::context::{BlockEnv, CfgEnv, TxEnv}; + +/// Helper container type for [`EvmEnv`] and [`OpTransaction`]. +#[derive(Clone, Debug, Default)] +pub struct Env { + pub evm_env: EvmEnv, + pub tx: OpTransaction, + pub is_optimism: bool, +} + +/// Helper container type for [`EvmEnv`] and [`OpTransaction`]. +impl Env { + pub fn new(cfg: CfgEnv, block: BlockEnv, tx: OpTransaction, is_optimism: bool) -> Self { + Self { evm_env: EvmEnv { cfg_env: cfg, block_env: block }, tx, is_optimism } + } +} + +impl AsEnvMut for Env { + fn as_env_mut(&mut self) -> EnvMut<'_> { + EnvMut { + block: &mut self.evm_env.block_env, + cfg: &mut self.evm_env.cfg_env, + tx: &mut self.tx.base, + } + } +} diff --git a/crates/anvil/src/eth/backend/executor.rs b/crates/anvil/src/eth/backend/executor.rs index 29b03756c17c8..2a036489fb2ce 100644 --- a/crates/anvil/src/eth/backend/executor.rs +++ b/crates/anvil/src/eth/backend/executor.rs @@ -1,17 +1,22 @@ use crate::{ eth::{ - backend::{db::Db, validate::TransactionValidator}, + backend::{ + db::Db, env::Env, mem::op_haltreason_to_instruction_result, + validate::TransactionValidator, + }, error::InvalidTransactionError, pool::transactions::PoolTransaction, }, - inject_precompiles, - mem::inspector::Inspector, + // inject_precompiles, + mem::inspector::AnvilInspector, PrecompileFactory, }; use alloy_consensus::{ constants::EMPTY_WITHDRAWALS, proofs::calculate_receipt_root, Receipt, ReceiptWithBloom, }; use alloy_eips::eip7685::EMPTY_REQUESTS_HASH; +use alloy_evm::{eth::EthEvmContext, EthEvm, Evm}; +use alloy_op_evm::OpEvm; use alloy_primitives::{Bloom, BloomInput, Log, B256}; use anvil_core::eth::{ block::{Block, BlockInfo, PartialHeader}, @@ -19,19 +24,18 @@ use anvil_core::eth::{ DepositReceipt, PendingTransaction, TransactionInfo, TypedReceipt, TypedTransaction, }, }; -use foundry_evm::{ - backend::DatabaseError, - revm::{ - interpreter::InstructionResult, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, EVMError, EnvWithHandlerCfg, ExecutionResult, Output, - SpecId, - }, - }, - traces::CallTraceNode, - utils::odyssey_handler_register, +use foundry_evm::{backend::DatabaseError, traces::CallTraceNode}; +use foundry_evm_core::{either_evm::EitherEvm, evm::FoundryPrecompiles}; +use op_revm::{L1BlockInfo, OpContext}; +use revm::{ + context::{Block as RevmBlock, BlockEnv, CfgEnv, Evm as RevmEvm, JournalTr}, + context_interface::result::{EVMError, ExecutionResult, Output}, + database::WrapDatabaseRef, + handler::instructions::EthInstructions, + interpreter::InstructionResult, + primitives::hardfork::SpecId, + Database, DatabaseRef, Inspector, Journal, }; -use revm::db::WrapDatabaseRef; use std::sync::Arc; /// Represents an executed transaction (transacted on the DB) @@ -100,7 +104,7 @@ pub struct TransactionExecutor<'a, Db: ?Sized, V: TransactionValidator> { pub pending: std::vec::IntoIter>, pub block_env: BlockEnv, /// The configuration environment and spec id - pub cfg_env: CfgEnvWithHandlerCfg, + pub cfg_env: CfgEnv, pub parent_hash: B256, /// Cumulative gas used by all executed transactions pub gas_used: u64, @@ -108,6 +112,7 @@ pub struct TransactionExecutor<'a, Db: ?Sized, V: TransactionValidator> { pub blob_gas_used: u64, pub enable_steps_tracing: bool, pub odyssey: bool, + pub optimism: bool, pub print_logs: bool, pub print_traces: bool, /// Precompiles to inject to the EVM. @@ -124,22 +129,22 @@ impl TransactionExecutor<'_, DB, V> { let mut cumulative_gas_used = 0u64; let mut invalid = Vec::new(); let mut included = Vec::new(); - let gas_limit = self.block_env.gas_limit.to::(); + let gas_limit = self.block_env.gas_limit; let parent_hash = self.parent_hash; - let block_number = self.block_env.number.to::(); + let block_number = self.block_env.number; let difficulty = self.block_env.difficulty; - let beneficiary = self.block_env.coinbase; - let timestamp = self.block_env.timestamp.to::(); - let base_fee = if self.cfg_env.handler_cfg.spec_id.is_enabled_in(SpecId::LONDON) { - Some(self.block_env.basefee.to::()) + let beneficiary = self.block_env.beneficiary; + let timestamp = self.block_env.timestamp; + let base_fee = if self.cfg_env.spec.is_enabled_in(SpecId::LONDON) { + Some(self.block_env.basefee) } else { None }; - let is_shanghai = self.cfg_env.handler_cfg.spec_id >= SpecId::SHANGHAI; - let is_cancun = self.cfg_env.handler_cfg.spec_id >= SpecId::CANCUN; - let is_prague = self.cfg_env.handler_cfg.spec_id >= SpecId::PRAGUE; - let excess_blob_gas = if is_cancun { self.block_env.get_blob_excess_gas() } else { None }; + let is_shanghai = self.cfg_env.spec >= SpecId::SHANGHAI; + let is_cancun = self.cfg_env.spec >= SpecId::CANCUN; + let is_prague = self.cfg_env.spec >= SpecId::PRAGUE; + let excess_blob_gas = if is_cancun { self.block_env.blob_excess_gas() } else { None }; let mut cumulative_blob_gas_used = if is_cancun { Some(0u64) } else { None }; for tx in self.into_iter() { @@ -241,14 +246,14 @@ impl TransactionExecutor<'_, DB, V> { ExecutedTransactions { block, included, invalid } } - fn env_for(&self, tx: &PendingTransaction) -> EnvWithHandlerCfg { + fn env_for(&self, tx: &PendingTransaction) -> Env { let mut tx_env = tx.to_revm_tx_env(); - if self.cfg_env.handler_cfg.is_optimism { - tx_env.optimism.enveloped_tx = - Some(alloy_rlp::encode(&tx.transaction.transaction).into()); + + if self.optimism { + tx_env.enveloped_tx = Some(alloy_rlp::encode(&tx.transaction.transaction).into()); } - EnvWithHandlerCfg::new_with_cfg_env(self.cfg_env.clone(), self.block_env.clone(), tx_env) + Env::new(self.cfg_env.clone(), self.block_env.clone(), tx_env, self.optimism) } } @@ -280,8 +285,9 @@ impl Iterator for &mut TransactionExec let env = self.env_for(&transaction.pending_transaction); // check that we comply with the block's gas limit, if not disabled - let max_gas = self.gas_used.saturating_add(env.tx.gas_limit); - if !env.cfg.disable_block_gas_limit && max_gas > env.block.gas_limit.to::() { + let max_gas = self.gas_used.saturating_add(env.tx.base.gas_limit); + if !env.evm_env.cfg_env.disable_block_gas_limit && max_gas > env.evm_env.block_env.gas_limit + { return Some(TransactionExecutionOutcome::Exhausted(transaction)) } @@ -300,13 +306,12 @@ impl Iterator for &mut TransactionExec &env, ) { warn!(target: "backend", "Skipping invalid tx execution [{:?}] {}", transaction.hash(), err); - return Some(TransactionExecutionOutcome::Invalid(transaction, err)) + return Some(TransactionExecutionOutcome::Invalid(transaction, err)); } let nonce = account.nonce; - // records all call and step traces - let mut inspector = Inspector::default().with_tracing(); + let mut inspector = AnvilInspector::default().with_tracing(); if self.enable_steps_tracing { inspector = inspector.with_steps_tracing(); } @@ -318,14 +323,14 @@ impl Iterator for &mut TransactionExec } let exec_result = { - let mut evm = new_evm_with_inspector(&mut *self.db, env, &mut inspector, self.odyssey); - if let Some(factory) = &self.precompile_factory { - inject_precompiles(&mut evm, factory.precompiles()); - } + let mut evm = new_evm_with_inspector(&mut *self.db, &env, &mut inspector); + // if let Some(factory) = &self.precompile_factory { + // inject_precompiles(&mut evm, factory.precompiles()); + // } trace!(target: "backend", "[{:?}] executing", transaction.hash()); // transact and commit the transaction - match evm.transact_commit() { + match evm.transact_commit(env.tx) { Ok(exec_result) => exec_result, Err(err) => { warn!(target: "backend", "[{:?}] failed to execute: {:?}", transaction.hash(), err); @@ -362,7 +367,9 @@ impl Iterator for &mut TransactionExec ExecutionResult::Revert { gas_used, output } => { (InstructionResult::Revert, gas_used, Some(Output::Call(output)), None) } - ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None, None), + ExecutionResult::Halt { reason, gas_used } => { + (op_haltreason_to_instruction_result(reason), gas_used, None, None) + } }; if exit_reason == InstructionResult::OutOfGas { @@ -407,35 +414,78 @@ fn build_logs_bloom(logs: Vec, bloom: &mut Bloom) { } /// Creates a database with given database and inspector, optionally enabling odyssey features. -pub fn new_evm_with_inspector( +pub fn new_evm_with_inspector( db: DB, - env: EnvWithHandlerCfg, - inspector: &mut dyn revm::Inspector, - odyssey: bool, -) -> revm::Evm<'_, &mut dyn revm::Inspector, DB> { - let EnvWithHandlerCfg { env, handler_cfg } = env; + env: &Env, + inspector: I, +) -> EitherEvm +where + DB: Database, + I: Inspector> + Inspector>, +{ + if env.is_optimism { + let op_context = OpContext { + journaled_state: { + let mut journal = Journal::new(db); + // Converting SpecId into OpSpecId + journal.set_spec_id(env.evm_env.cfg_env.spec); + journal + }, + block: env.evm_env.block_env.clone(), + cfg: env.evm_env.cfg_env.clone().with_spec(op_revm::OpSpecId::BEDROCK), + tx: env.tx.clone(), + chain: L1BlockInfo::default(), + error: Ok(()), + }; - let mut handler = revm::Handler::new(handler_cfg); + let evm = op_revm::OpEvm(RevmEvm::new_with_inspector( + op_context, + inspector, + EthInstructions::default(), + FoundryPrecompiles::default(), + )); + + let op = OpEvm::new(evm, true); + + EitherEvm::Op(op) + } else { + let evm_context = EthEvmContext { + journaled_state: { + let mut journal = Journal::new(db); + journal.set_spec_id(env.evm_env.cfg_env.spec); + journal + }, + block: env.evm_env.block_env.clone(), + cfg: env.evm_env.cfg_env.clone(), + tx: env.tx.base.clone(), + chain: (), + error: Ok(()), + }; - handler.append_handler_register_plain(revm::inspector_handle_register); - if odyssey { - handler.append_handler_register_plain(odyssey_handler_register); - } + let evm = RevmEvm::new_with_inspector( + evm_context, + inspector, + EthInstructions::default(), + FoundryPrecompiles::new(), + ); - let context = revm::Context::new(revm::EvmContext::new_with_env(db, env), inspector); + let eth = EthEvm::new(evm, true); - revm::Evm::new(context, handler) + EitherEvm::Eth(eth) + } } /// Creates a new EVM with the given inspector and wraps the database in a `WrapDatabaseRef`. -pub fn new_evm_with_inspector_ref<'a, DB>( - db: DB, - env: EnvWithHandlerCfg, - inspector: &mut dyn revm::Inspector>, - odyssey: bool, -) -> revm::Evm<'a, &mut dyn revm::Inspector>, WrapDatabaseRef> +pub fn new_evm_with_inspector_ref<'db, DB, I>( + db: &'db DB, + env: &Env, + inspector: &'db mut I, +) -> EitherEvm, &'db mut I, FoundryPrecompiles> where - DB: revm::DatabaseRef, + DB: DatabaseRef + 'db + ?Sized, + I: Inspector>> + + Inspector>>, + WrapDatabaseRef<&'db DB>: Database, { - new_evm_with_inspector(WrapDatabaseRef(db), env, inspector, odyssey) + new_evm_with_inspector(WrapDatabaseRef(db), env, inspector) } diff --git a/crates/anvil/src/eth/backend/fork.rs b/crates/anvil/src/eth/backend/fork.rs index ea8a9894cdf55..841d740abc44f 100644 --- a/crates/anvil/src/eth/backend/fork.rs +++ b/crates/anvil/src/eth/backend/fork.rs @@ -30,7 +30,7 @@ use parking_lot::{ lock_api::{RwLockReadGuard, RwLockWriteGuard}, RawRwLock, RwLock, }; -use revm::primitives::BlobExcessGasAndPrice; +use revm::context_interface::block::BlobExcessGasAndPrice; use std::{sync::Arc, time::Duration}; use tokio::sync::RwLock as AsyncRwLock; diff --git a/crates/anvil/src/eth/backend/genesis.rs b/crates/anvil/src/eth/backend/genesis.rs index 649717bd1cdf8..597dd1ee2d179 100644 --- a/crates/anvil/src/eth/backend/genesis.rs +++ b/crates/anvil/src/eth/backend/genesis.rs @@ -3,10 +3,8 @@ use crate::eth::backend::db::Db; use alloy_genesis::{Genesis, GenesisAccount}; use alloy_primitives::{Address, U256}; -use foundry_evm::{ - backend::DatabaseResult, - revm::primitives::{AccountInfo, Bytecode, KECCAK_EMPTY}, -}; +use foundry_evm::backend::DatabaseResult; +use revm::{bytecode::Bytecode, primitives::KECCAK_EMPTY, state::AccountInfo}; use tokio::sync::RwLockWriteGuard; /// Genesis settings diff --git a/crates/anvil/src/eth/backend/mem/fork_db.rs b/crates/anvil/src/eth/backend/mem/fork_db.rs index be5c3bcd7b32e..56a4944ada5a8 100644 --- a/crates/anvil/src/eth/backend/mem/fork_db.rs +++ b/crates/anvil/src/eth/backend/mem/fork_db.rs @@ -1,20 +1,20 @@ -use crate::{ - eth::backend::db::{ - Db, MaybeForkedDatabase, MaybeFullDatabase, SerializableAccountRecord, SerializableBlock, - SerializableHistoricalStates, SerializableState, SerializableTransaction, StateDb, - }, - revm::primitives::AccountInfo, +use crate::eth::backend::db::{ + Db, MaybeForkedDatabase, MaybeFullDatabase, SerializableAccountRecord, SerializableBlock, + SerializableHistoricalStates, SerializableState, SerializableTransaction, StateDb, }; -use alloy_primitives::{map::HashMap, Address, B256, U256, U64}; +use alloy_primitives::{map::HashMap, Address, B256, U256}; use alloy_rpc_types::BlockId; use foundry_evm::{ backend::{ BlockchainDb, DatabaseError, DatabaseResult, RevertStateSnapshotAction, StateSnapshot, }, fork::database::ForkDbStateSnapshot, - revm::{primitives::BlockEnv, Database}, }; -use revm::{db::DbAccount, DatabaseRef}; +use revm::{ + context::BlockEnv, + database::{Database, DatabaseRef, DbAccount}, + state::AccountInfo, +}; pub use foundry_evm::fork::database::ForkedDatabase; @@ -36,7 +36,7 @@ impl Db for ForkedDatabase { fn dump_state( &self, at: BlockEnv, - best_number: U64, + best_number: u64, blocks: Vec, transactions: Vec, historical_states: Option, @@ -44,6 +44,7 @@ impl Db for ForkedDatabase { let mut db = self.database().clone(); let accounts = self .database() + .cache .accounts .clone() .into_iter() @@ -93,7 +94,7 @@ impl MaybeFullDatabase for ForkedDatabase { } fn maybe_as_full_db(&self) -> Option<&HashMap> { - Some(&self.database().accounts) + Some(&self.database().cache.accounts) } fn clear_into_state_snapshot(&mut self) -> StateSnapshot { @@ -132,7 +133,7 @@ impl MaybeFullDatabase for ForkDbStateSnapshot { } fn maybe_as_full_db(&self) -> Option<&HashMap> { - Some(&self.local.accounts) + Some(&self.local.cache.accounts) } fn clear_into_state_snapshot(&mut self) -> StateSnapshot { diff --git a/crates/anvil/src/eth/backend/mem/in_memory_db.rs b/crates/anvil/src/eth/backend/mem/in_memory_db.rs index adc9c6f1f44b7..08a78b43406c7 100644 --- a/crates/anvil/src/eth/backend/mem/in_memory_db.rs +++ b/crates/anvil/src/eth/backend/mem/in_memory_db.rs @@ -6,15 +6,19 @@ use crate::{ SerializableHistoricalStates, SerializableState, SerializableTransaction, StateDb, }, mem::state::state_root, - revm::{db::DbAccount, primitives::AccountInfo}, }; -use alloy_primitives::{map::HashMap, Address, B256, U256, U64}; +use alloy_primitives::{map::HashMap, Address, B256, U256}; use alloy_rpc_types::BlockId; use foundry_evm::backend::{BlockchainDb, DatabaseResult, StateSnapshot}; +use revm::{ + context::BlockEnv, + database::{DatabaseRef, DbAccount}, + state::AccountInfo, +}; // reexport for convenience -pub use foundry_evm::{backend::MemDb, revm::db::DatabaseRef}; -use foundry_evm::{backend::RevertStateSnapshotAction, revm::primitives::BlockEnv}; +pub use foundry_evm::backend::MemDb; +use foundry_evm::backend::RevertStateSnapshotAction; impl Db for MemDb { fn insert_account(&mut self, address: Address, account: AccountInfo) { @@ -26,19 +30,20 @@ impl Db for MemDb { } fn insert_block_hash(&mut self, number: U256, hash: B256) { - self.inner.block_hashes.insert(number, hash); + self.inner.cache.block_hashes.insert(number, hash); } fn dump_state( &self, at: BlockEnv, - best_number: U64, + best_number: u64, blocks: Vec, transactions: Vec, historical_states: Option, ) -> DatabaseResult> { let accounts = self .inner + .cache .accounts .clone() .into_iter() @@ -92,7 +97,7 @@ impl Db for MemDb { } fn maybe_state_root(&self) -> Option { - Some(state_root(&self.inner.accounts)) + Some(state_root(&self.inner.cache.accounts)) } fn current_state(&self) -> StateDb { @@ -106,7 +111,7 @@ impl MaybeFullDatabase for MemDb { } fn maybe_as_full_db(&self) -> Option<&HashMap> { - Some(&self.inner.accounts) + Some(&self.inner.cache.accounts) } fn clear_into_state_snapshot(&mut self) -> StateSnapshot { @@ -144,7 +149,7 @@ impl MaybeForkedDatabase for MemDb { mod tests { use super::*; use alloy_primitives::{address, Bytes}; - use foundry_evm::revm::primitives::{Bytecode, KECCAK_EMPTY}; + use revm::{bytecode::Bytecode, primitives::KECCAK_EMPTY}; use std::collections::BTreeMap; // verifies that all substantial aspects of a loaded account remain the same after an account @@ -171,7 +176,7 @@ mod tests { // blocks dumping/loading tested in storage.rs let state = dump_db - .dump_state(Default::default(), U64::ZERO, Vec::new(), Vec::new(), Default::default()) + .dump_state(Default::default(), 0, Vec::new(), Vec::new(), Default::default()) .unwrap() .unwrap(); diff --git a/crates/anvil/src/eth/backend/mem/inspector.rs b/crates/anvil/src/eth/backend/mem/inspector.rs index 9a68b70612461..b850af64300bf 100644 --- a/crates/anvil/src/eth/backend/mem/inspector.rs +++ b/crates/anvil/src/eth/backend/mem/inspector.rs @@ -1,33 +1,37 @@ //! Anvil specific [`revm::Inspector`] implementation -use crate::{eth::macros::node_info, revm::Database}; -use alloy_primitives::{Address, Log}; +use crate::eth::macros::node_info; +use alloy_evm::eth::EthEvmContext; +use alloy_primitives::{Address, Log, U256}; use foundry_evm::{ + backend::DatabaseError, call_inspectors, decode::decode_console_logs, inspectors::{LogCollector, TracingInspector}, - revm::{ - interpreter::{ - CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Interpreter, - }, - primitives::U256, - EvmContext, - }, traces::{ render_trace_arena_inner, CallTraceDecoder, SparsedTraceArena, TracingInspectorConfig, }, }; +use revm::{ + context::ContextTr, + inspector::JournalExt, + interpreter::{ + interpreter::EthInterpreter, CallInputs, CallOutcome, CreateInputs, CreateOutcome, + EOFCreateInputs, Interpreter, + }, + Database, Inspector, +}; /// The [`revm::Inspector`] used when transacting in the evm #[derive(Clone, Debug, Default)] -pub struct Inspector { +pub struct AnvilInspector { /// Collects all traces pub tracer: Option, /// Collects all `console.sol` logs pub log_collector: Option, } -impl Inspector { +impl AnvilInspector { /// Called after the inspecting the evm /// /// This will log all `console.sol` logs @@ -104,32 +108,38 @@ fn print_traces(tracer: TracingInspector) { node_info!("{}", render_trace_arena_inner(&traces, false, true)); } -impl revm::Inspector for Inspector { - fn initialize_interp(&mut self, interp: &mut Interpreter, ecx: &mut EvmContext) { +impl Inspector for AnvilInspector +where + D: Database, + CTX: ContextTr, + CTX::Journal: JournalExt, +{ + fn initialize_interp(&mut self, interp: &mut Interpreter, ecx: &mut CTX) { call_inspectors!([&mut self.tracer], |inspector| { inspector.initialize_interp(interp, ecx); }); } - fn step(&mut self, interp: &mut Interpreter, ecx: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, ecx: &mut CTX) { call_inspectors!([&mut self.tracer], |inspector| { inspector.step(interp, ecx); }); } - fn step_end(&mut self, interp: &mut Interpreter, ecx: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, ecx: &mut CTX) { call_inspectors!([&mut self.tracer], |inspector| { inspector.step_end(interp, ecx); }); } - fn log(&mut self, interp: &mut Interpreter, ecx: &mut EvmContext, log: &Log) { + fn log(&mut self, interp: &mut Interpreter, ecx: &mut CTX, log: Log) { call_inspectors!([&mut self.tracer, &mut self.log_collector], |inspector| { - inspector.log(interp, ecx, log); + // TODO: rm the log.clone + inspector.log(interp, ecx, log.clone()); }); } - fn call(&mut self, ecx: &mut EvmContext, inputs: &mut CallInputs) -> Option { + fn call(&mut self, ecx: &mut CTX, inputs: &mut CallInputs) -> Option { call_inspectors!( #[ret] [&mut self.tracer, &mut self.log_collector], @@ -138,24 +148,13 @@ impl revm::Inspector for Inspector { None } - fn call_end( - &mut self, - ecx: &mut EvmContext, - inputs: &CallInputs, - outcome: CallOutcome, - ) -> CallOutcome { + fn call_end(&mut self, ecx: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) { if let Some(tracer) = &mut self.tracer { - return tracer.call_end(ecx, inputs, outcome); + tracer.call_end(ecx, inputs, outcome); } - - outcome } - fn create( - &mut self, - ecx: &mut EvmContext, - inputs: &mut CreateInputs, - ) -> Option { + fn create(&mut self, ecx: &mut CTX, inputs: &mut CreateInputs) -> Option { if let Some(tracer) = &mut self.tracer { if let Some(out) = tracer.create(ecx, inputs) { return Some(out); @@ -164,25 +163,14 @@ impl revm::Inspector for Inspector { None } - fn create_end( - &mut self, - ecx: &mut EvmContext, - inputs: &CreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + fn create_end(&mut self, ecx: &mut CTX, inputs: &CreateInputs, outcome: &mut CreateOutcome) { if let Some(tracer) = &mut self.tracer { - return tracer.create_end(ecx, inputs, outcome); + tracer.create_end(ecx, inputs, outcome); } - - outcome } #[inline] - fn eofcreate( - &mut self, - ecx: &mut EvmContext, - inputs: &mut EOFCreateInputs, - ) -> Option { + fn eofcreate(&mut self, ecx: &mut CTX, inputs: &mut EOFCreateInputs) -> Option { if let Some(tracer) = &mut self.tracer { if let Some(out) = tracer.eofcreate(ecx, inputs) { return Some(out); @@ -194,21 +182,19 @@ impl revm::Inspector for Inspector { #[inline] fn eofcreate_end( &mut self, - ecx: &mut EvmContext, + ecx: &mut CTX, inputs: &EOFCreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + outcome: &mut CreateOutcome, + ) { if let Some(tracer) = &mut self.tracer { - return tracer.eofcreate_end(ecx, inputs, outcome); + tracer.eofcreate_end(ecx, inputs, outcome); } - - outcome } #[inline] fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { if let Some(tracer) = &mut self.tracer { - revm::Inspector::::selfdestruct(tracer, contract, target, value); + Inspector::>::selfdestruct(tracer, contract, target, value); } } } diff --git a/crates/anvil/src/eth/backend/mem/mod.rs b/crates/anvil/src/eth/backend/mem/mod.rs index 0cb4ad0ab65f9..35cbe1b19d6d2 100644 --- a/crates/anvil/src/eth/backend/mem/mod.rs +++ b/crates/anvil/src/eth/backend/mem/mod.rs @@ -1,13 +1,13 @@ //! In-memory blockchain backend. use self::state::trie_storage; -use super::executor::new_evm_with_inspector_ref; use crate::{ config::PruneStateHistoryConfig, eth::{ backend::{ cheats::CheatsManager, db::{Db, MaybeFullDatabase, SerializableState}, + env::Env, executor::{ExecutedTransactions, TransactionExecutor}, fork::ClientFork, genesis::GenesisConfig, @@ -26,29 +26,38 @@ use crate::{ sign::build_typed_transaction, util::get_precompiles_for, }, - inject_precompiles, + // inject_precompiles, mem::{ - inspector::Inspector, + inspector::AnvilInspector, storage::{BlockchainStorage, InMemoryBlockStates, MinedBlockOutcome}, }, - revm::{db::DatabaseRef, primitives::AccountInfo}, - ForkChoice, NodeConfig, PrecompileFactory, + ForkChoice, + NodeConfig, + PrecompileFactory, }; use alloy_chains::NamedChain; use alloy_consensus::{ proofs::{calculate_receipt_root, calculate_transaction_root}, transaction::Recovered, - Account, BlockHeader, Header, Receipt, ReceiptWithBloom, Signed, + Account, BlockHeader, EnvKzgSettings, Header, Receipt, ReceiptWithBloom, Signed, Transaction as TransactionTrait, TxEnvelope, }; -use alloy_eips::{eip1559::BaseFeeParams, eip4844::MAX_BLOBS_PER_BLOCK}; +use alloy_eips::{ + eip1559::BaseFeeParams, + eip2718::{ + EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, EIP7702_TX_TYPE_ID, + LEGACY_TX_TYPE_ID, + }, + eip4844::MAX_BLOBS_PER_BLOCK, +}; +use alloy_evm::{eth::EthEvmContext, Database, Evm}; use alloy_network::{ AnyHeader, AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, AnyTxEnvelope, AnyTxType, EthereumWallet, UnknownTxEnvelope, UnknownTypedTransaction, }; use alloy_primitives::{ - address, hex, keccak256, logs_bloom, utils::Unit, Address, Bytes, TxHash, TxKind, B256, U256, - U64, + address, hex, keccak256, logs_bloom, map::HashMap, utils::Unit, Address, Bytes, TxHash, TxKind, + B256, U256, U64, }; use alloy_rpc_types::{ anvil::Forking, @@ -75,9 +84,9 @@ use alloy_trie::{proof::ProofRetainer, HashBuilder, Nibbles}; use anvil_core::eth::{ block::{Block, BlockInfo}, transaction::{ - optimism::DepositTransaction, transaction_request_to_typed, DepositReceipt, - MaybeImpersonatedTransaction, PendingTransaction, ReceiptResponse, TransactionInfo, - TypedReceipt, TypedTransaction, + has_optimism_fields, optimism::DepositTransaction, transaction_request_to_typed, + DepositReceipt, MaybeImpersonatedTransaction, PendingTransaction, ReceiptResponse, + TransactionInfo, TypedReceipt, TypedTransaction, }, wallet::{Capabilities, DelegationCapability, WalletCapabilities}, }; @@ -90,24 +99,26 @@ use foundry_evm::{ constants::DEFAULT_CREATE2_DEPLOYER_RUNTIME_CODE, decode::RevertDecoder, inspectors::AccessListInspector, - revm::{ - db::CacheDB, - interpreter::InstructionResult, - primitives::{ - BlockEnv, CfgEnvWithHandlerCfg, EnvWithHandlerCfg, ExecutionResult, Output, SpecId, - TxEnv, KECCAK_EMPTY, - }, - }, traces::TracingInspectorConfig, }; +use foundry_evm_core::{either_evm::EitherEvm, evm::FoundryPrecompiles}; use futures::channel::mpsc::{unbounded, UnboundedSender}; use op_alloy_consensus::{TxDeposit, DEPOSIT_TX_TYPE_ID}; +use op_revm::{ + transaction::deposit::DepositTransactionParts, OpContext, OpHaltReason, OpTransaction, +}; use parking_lot::{Mutex, RwLock}; use revm::{ - db::WrapDatabaseRef, - interpreter::Host, - primitives::{BlobExcessGasAndPrice, HashMap, OptimismFields, ResultAndState}, - DatabaseCommit, + context::{Block as RevmBlock, BlockEnv, TxEnv}, + context_interface::{ + block::BlobExcessGasAndPrice, + result::{ExecutionResult, Output, ResultAndState}, + }, + database::{CacheDB, DatabaseRef, WrapDatabaseRef}, + interpreter::InstructionResult, + primitives::{hardfork::SpecId, KECCAK_EMPTY}, + state::AccountInfo, + DatabaseCommit, Inspector, }; use revm_inspectors::transfer::TransferInspector; use std::{ @@ -121,6 +132,8 @@ use std::{ use storage::{Blockchain, MinedTransaction, DEFAULT_HISTORY_LIMIT}; use tokio::sync::RwLock as AsyncRwLock; +use super::executor::new_evm_with_inspector_ref; + pub mod cache; pub mod fork_db; pub mod in_memory_db; @@ -168,29 +181,30 @@ impl BlockRequest { pub struct Backend { /// Access to [`revm::Database`] abstraction. /// - /// This will be used in combination with [`revm::Evm`] and is responsible for feeding data to - /// the evm during its execution. + /// This will be used in combination with [`alloy_evm::Evm`] and is responsible for feeding + /// data to the evm during its execution. /// /// At time of writing, there are two different types of `Db`: /// - [`MemDb`](crate::mem::in_memory_db::MemDb): everything is stored in memory /// - [`ForkDb`](crate::mem::fork_db::ForkedDatabase): forks off a remote client, missing /// data is retrieved via RPC-calls /// - /// In order to commit changes to the [`revm::Database`], the [`revm::Evm`] requires mutable - /// access, which requires a write-lock from this `db`. In forking mode, the time during - /// which the write-lock is active depends on whether the `ForkDb` can provide all requested - /// data from memory or whether it has to retrieve it via RPC calls first. This means that it - /// potentially blocks for some time, even taking into account the rate limits of RPC - /// endpoints. Therefore the `Db` is guarded by a `tokio::sync::RwLock` here so calls that - /// need to read from it, while it's currently written to, don't block. E.g. a new block is - /// currently mined and a new [`Self::set_storage_at()`] request is being executed. + /// In order to commit changes to the [`revm::Database`], the [`alloy_evm::Evm`] requires + /// mutable access, which requires a write-lock from this `db`. In forking mode, the time + /// during which the write-lock is active depends on whether the `ForkDb` can provide all + /// requested data from memory or whether it has to retrieve it via RPC calls first. This + /// means that it potentially blocks for some time, even taking into account the rate + /// limits of RPC endpoints. Therefore the `Db` is guarded by a `tokio::sync::RwLock` here + /// so calls that need to read from it, while it's currently written to, don't block. E.g. + /// a new block is currently mined and a new [`Self::set_storage_at()`] request is being + /// executed. db: Arc>>, /// stores all block related data in memory. blockchain: Blockchain, /// Historic states of previous blocks. states: Arc>, /// Env data of the chain - env: Arc>, + env: Arc>, /// This is set if this is currently forked off another client. fork: Arc>>, /// Provides time related info, like timestamp. @@ -230,7 +244,7 @@ impl Backend { #[expect(clippy::too_many_arguments)] pub async fn with_genesis( db: Arc>>, - env: Arc>, + env: Arc>, genesis: GenesisConfig, fees: FeeManager, fork: Arc>>, @@ -253,7 +267,7 @@ impl Backend { let env = env.read(); Blockchain::new( &env, - env.handler_cfg.spec_id, + env.evm_env.cfg_env.spec, fees.is_eip1559().then(|| fees.base_fee()), genesis.timestamp, genesis.number, @@ -310,7 +324,7 @@ impl Backend { let mut capabilities = WalletCapabilities::default(); - let chain_id = env.read().cfg.chain_id; + let chain_id = env.read().evm_env.cfg_env.chain_id; capabilities.insert( chain_id, Capabilities { @@ -389,7 +403,7 @@ impl Backend { /// Adds an address to the [`DelegationCapability`] of the wallet. pub(crate) fn add_capability(&self, address: Address) { - let chain_id = self.env.read().cfg.chain_id; + let chain_id = self.env.read().evm_env.cfg_env.chain_id; let mut capabilities = self.capabilities.write(); let mut capability = capabilities.get(chain_id).cloned().unwrap_or_default(); capability.delegation.addresses.push(address); @@ -467,7 +481,7 @@ impl Backend { } // Ensure EIP-3607 is disabled let mut env = self.env.write(); - env.cfg.disable_eip3607 = true; + env.evm_env.cfg_env.disable_eip3607 = true; self.cheats.impersonate(addr) } @@ -504,7 +518,7 @@ impl Backend { } pub fn precompiles(&self) -> Vec
{ - get_precompiles_for(self.env.read().handler_cfg.spec_id) + get_precompiles_for(self.env.read().evm_env.cfg_env.spec) } /// Resets the fork to a fresh state @@ -564,23 +578,23 @@ impl Backend { let gas_limit = self.node_config.read().await.fork_gas_limit(&fork_block); let mut env = self.env.write(); - env.cfg.chain_id = fork.chain_id(); - env.block = BlockEnv { - number: U256::from(fork_block_number), - timestamp: U256::from(fork_block.header.timestamp), - gas_limit: U256::from(gas_limit), + env.evm_env.cfg_env.chain_id = fork.chain_id(); + env.evm_env.block_env = BlockEnv { + number: fork_block_number, + timestamp: fork_block.header.timestamp, + gas_limit, difficulty: fork_block.header.difficulty, prevrandao: Some(fork_block.header.mix_hash.unwrap_or_default()), - // Keep previous `coinbase` and `basefee` value - coinbase: env.block.coinbase, - basefee: env.block.basefee, - ..env.block.clone() + // Keep previous `beneficiary` and `basefee` value + beneficiary: env.evm_env.block_env.beneficiary, + basefee: env.evm_env.block_env.basefee, + ..env.evm_env.block_env.clone() }; // this is the base fee of the current block, but we need the base fee of // the next block let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas( - fork_block.header.gas_used as u128, + fork_block.header.gas_used, gas_limit, fork_block.header.base_fee_per_gas.unwrap_or_default(), ); @@ -656,7 +670,7 @@ impl Backend { } /// The env data of the blockchain - pub fn env(&self) -> &Arc> { + pub fn env(&self) -> &Arc> { &self.env } @@ -667,27 +681,27 @@ impl Backend { /// Returns the current best number of the chain pub fn best_number(&self) -> u64 { - self.blockchain.storage.read().best_number.try_into().unwrap_or(u64::MAX) + self.blockchain.storage.read().best_number } /// Sets the block number - pub fn set_block_number(&self, number: U256) { + pub fn set_block_number(&self, number: u64) { let mut env = self.env.write(); - env.block.number = number; + env.evm_env.block_env.number = number; } /// Returns the client coinbase address. pub fn coinbase(&self) -> Address { - self.env.read().block.coinbase + self.env.read().evm_env.block_env.beneficiary } /// Returns the client coinbase address. pub fn chain_id(&self) -> U256 { - U256::from(self.env.read().cfg.chain_id) + U256::from(self.env.read().evm_env.cfg_env.chain_id) } pub fn set_chain_id(&self, chain_id: u64) { - self.env.write().cfg.chain_id = chain_id; + self.env.write().evm_env.cfg_env.chain_id = chain_id; } /// Returns balance of the given account. @@ -702,7 +716,7 @@ impl Backend { /// Sets the coinbase address pub fn set_coinbase(&self, address: Address) { - self.env.write().block.coinbase = address; + self.env.write().evm_env.block_env.beneficiary = address; } /// Sets the nonce of the given address @@ -732,7 +746,7 @@ impl Backend { /// Returns the configured specid pub fn spec_id(&self) -> SpecId { - self.env.read().handler_cfg.spec_id + self.env.read().evm_env.cfg_env.spec } /// Returns true for post London @@ -762,7 +776,7 @@ impl Backend { /// Returns true if op-stack deposits are active pub fn is_optimism(&self) -> bool { - self.env.read().handler_cfg.is_optimism + self.env.read().is_optimism } /// Returns an error if EIP1559 is not active (pre Berlin) @@ -805,12 +819,12 @@ impl Backend { /// Returns the block gas limit pub fn gas_limit(&self) -> u64 { - self.env.read().block.gas_limit.saturating_to() + self.env.read().evm_env.block_env.gas_limit } /// Sets the block gas limit pub fn set_gas_limit(&self, gas_limit: u64) { - self.env.write().block.gas_limit = U256::from(gas_limit); + self.env.write().evm_env.block_env.gas_limit = gas_limit; } /// Returns the current base fee @@ -872,7 +886,6 @@ impl Backend { for n in ((num + 1)..=current_height).rev() { trace!(target: "backend", "reverting block {}", n); - let n = U64::from(n); if let Some(hash) = storage.hashes.remove(&n) { if let Some(block) = storage.blocks.remove(&hash) { for tx in block.transactions { @@ -882,7 +895,7 @@ impl Backend { } } - storage.best_number = U64::from(num); + storage.best_number = num; storage.best_hash = hash; hash }; @@ -893,18 +906,18 @@ impl Backend { self.time.reset(reset_time); let mut env = self.env.write(); - env.block = BlockEnv { - number: U256::from(num), - timestamp: U256::from(block.header.timestamp), + env.evm_env.block_env = BlockEnv { + number: num, + timestamp: block.header.timestamp, difficulty: block.header.difficulty, // ensures prevrandao is set prevrandao: Some(block.header.mix_hash.unwrap_or_default()), - gas_limit: U256::from(block.header.gas_limit), - // Keep previous `coinbase` and `basefee` value - coinbase: env.block.coinbase, - basefee: env.block.basefee, + gas_limit: block.header.gas_limit, + // Keep previous `beneficiary` and `basefee` value + beneficiary: env.evm_env.block_env.beneficiary, + basefee: env.evm_env.block_env.basefee, ..Default::default() - }; + } } Ok(self.db.write().await.revert_state(id, RevertStateSnapshotAction::RevertRemove)) } @@ -918,7 +931,7 @@ impl Backend { &self, preserve_historical_states: bool, ) -> Result { - let at = self.env.read().block.clone(); + let at = self.env.read().evm_env.block_env.clone(); let best_number = self.blockchain.storage.read().best_number; let blocks = self.blockchain.storage.read().serialized_blocks(); let transactions = self.blockchain.storage.read().serialized_transactions(); @@ -961,19 +974,19 @@ impl Backend { self.blockchain.storage.write().load_transactions(state.transactions.clone()); // reset the block env if let Some(block) = state.block.clone() { - self.env.write().block = block.clone(); + self.env.write().evm_env.block_env = block.clone(); // Set the current best block number. // Defaults to block number for compatibility with existing state files. let fork_num_and_hash = self.get_fork().map(|f| (f.block_number(), f.block_hash())); if let Some((number, hash)) = fork_num_and_hash { - let best_number = state.best_block_number.unwrap_or(block.number.to::()); + let best_number = state.best_block_number.unwrap_or(block.number); trace!(target: "backend", state_block_number=?best_number, fork_block_number=?number); // If the state.block_number is greater than the fork block number, set best number // to the state block number. // Ref: https://github.com/foundry-rs/foundry/issues/9539 - if best_number.to::() > number { + if best_number > number { self.blockchain.storage.write().best_number = best_number; let best_hash = self.blockchain.storage.read().hash(best_number.into()).ok_or_else( @@ -987,11 +1000,11 @@ impl Backend { } else { // If loading state file on a fork, set best number to the fork block number. // Ref: https://github.com/foundry-rs/foundry/pull/9215#issue-2618681838 - self.blockchain.storage.write().best_number = U64::from(number); + self.blockchain.storage.write().best_number = number; self.blockchain.storage.write().best_hash = hash; } } else { - let best_number = state.best_block_number.unwrap_or(block.number.to::()); + let best_number = state.best_block_number.unwrap_or(block.number); self.blockchain.storage.write().best_number = best_number; // Set the current best block hash; @@ -1009,13 +1022,13 @@ impl Backend { if let Some(latest) = state.blocks.iter().max_by_key(|b| b.header.number) { let header = &latest.header; let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas( - header.gas_used as u128, - header.gas_limit as u128, + header.gas_used, + header.gas_limit, header.base_fee_per_gas.unwrap_or_default(), ); let next_block_excess_blob_gas = self.fees.get_next_block_blob_excess_gas( - header.excess_blob_gas.map(|g| g as u128).unwrap_or_default(), - header.blob_gas_used.map(|g| g as u128).unwrap_or_default(), + header.excess_blob_gas.unwrap_or_default(), + header.blob_gas_used.unwrap_or_default(), ); // update next base fee @@ -1060,34 +1073,37 @@ impl Backend { } /// Returns the environment for the next block - fn next_env(&self) -> EnvWithHandlerCfg { + fn next_env(&self) -> Env { let mut env = self.env.read().clone(); // increase block number for this block - env.block.number = env.block.number.saturating_add(U256::from(1)); - env.block.basefee = U256::from(self.base_fee()); - env.block.timestamp = U256::from(self.time.current_call_timestamp()); + env.evm_env.block_env.number = env.evm_env.block_env.number.saturating_add(1); + env.evm_env.block_env.basefee = self.base_fee(); + env.evm_env.block_env.timestamp = self.time.current_call_timestamp(); env } /// Creates an EVM instance with optionally injected precompiles. - #[expect(clippy::type_complexity)] - fn new_evm_with_inspector_ref<'i, 'db>( + fn new_evm_with_inspector_ref<'db, I>( &self, db: &'db dyn DatabaseRef, - env: EnvWithHandlerCfg, - inspector: &'i mut dyn revm::Inspector< - WrapDatabaseRef<&'db dyn DatabaseRef>, - >, - ) -> revm::Evm< - '_, - &'i mut dyn revm::Inspector>>, + env: &Env, + inspector: &'db mut I, + ) -> EitherEvm< WrapDatabaseRef<&'db dyn DatabaseRef>, - > { - let mut evm = new_evm_with_inspector_ref(db, env, inspector, self.odyssey); - if let Some(factory) = &self.precompile_factory { - inject_precompiles(&mut evm, factory.precompiles()); - } - evm + &'db mut I, + FoundryPrecompiles, + > + where + I: Inspector>>> + + Inspector>>>, + WrapDatabaseRef<&'db dyn DatabaseRef>: + Database, + { + new_evm_with_inspector_ref(db, env, inspector) + // TODO(yash): inject precompiles + // if let Some(factory) = &self.precompile_factory { + // inject_precompiles(&mut evm, factory.precompiles()); + // } } /// executes the transactions without writing to the underlying database @@ -1101,15 +1117,15 @@ impl Backend { let mut env = self.next_env(); env.tx = tx.pending_transaction.to_revm_tx_env(); - if env.handler_cfg.is_optimism { - env.tx.optimism.enveloped_tx = + if env.is_optimism { + env.tx.enveloped_tx = Some(alloy_rlp::encode(&tx.pending_transaction.transaction.transaction).into()); } let db = self.db.read().await; let mut inspector = self.build_inspector(); - let mut evm = self.new_evm_with_inspector_ref(db.as_dyn(), env, &mut inspector); - let ResultAndState { result, state } = evm.transact()?; + let mut evm = self.new_evm_with_inspector_ref(db.as_dyn(), &env, &mut inspector); + let ResultAndState { result, state } = evm.transact(env.tx)?; let (exit_reason, gas_used, out, logs) = match result { ExecutionResult::Success { reason, gas_used, logs, output, .. } => { (reason.into(), gas_used, Some(output), Some(logs)) @@ -1117,7 +1133,10 @@ impl Backend { ExecutionResult::Revert { gas_used, output } => { (InstructionResult::Revert, gas_used, Some(Output::Call(output)), None) } - ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None, None), + ExecutionResult::Halt { reason, gas_used } => { + let eth_reason = op_haltreason_to_instruction_result(reason); + (eth_reason, gas_used, None, None) + } }; drop(evm); @@ -1155,13 +1174,12 @@ impl Backend { let storage = self.blockchain.storage.read(); - let cfg_env = CfgEnvWithHandlerCfg::new(env.cfg.clone(), env.handler_cfg); let executor = TransactionExecutor { db: &mut cache_db, validator: self, pending: pool_transactions.into_iter(), - block_env: env.block.clone(), - cfg_env, + block_env: env.evm_env.block_env.clone(), + cfg_env: env.evm_env.cfg_env, parent_hash: storage.best_hash, gas_used: 0, blob_gas_used: 0, @@ -1170,6 +1188,7 @@ impl Backend { print_traces: self.print_traces, precompile_factory: self.precompile_factory.clone(), odyssey: self.odyssey, + optimism: self.is_optimism(), }; // create a new pending block @@ -1201,28 +1220,27 @@ impl Backend { let mut env = self.env.read().clone(); - if env.block.basefee.is_zero() { + if env.evm_env.block_env.basefee == 0 { // this is an edge case because the evm fails if `tx.effective_gas_price < base_fee` // 0 is only possible if it's manually set - env.cfg.disable_base_fee = true; + env.evm_env.cfg_env.disable_base_fee = true; } - let block_number = - self.blockchain.storage.read().best_number.saturating_add(U64::from(1)); + let block_number = self.blockchain.storage.read().best_number.saturating_add(1); // increase block number for this block - if is_arbitrum(env.cfg.chain_id) { + if is_arbitrum(env.evm_env.cfg_env.chain_id) { // Temporary set `env.block.number` to `block_number` for Arbitrum chains. - env.block.number = block_number.to(); + env.evm_env.block_env.number = block_number; } else { - env.block.number = env.block.number.saturating_add(U256::from(1)); + env.evm_env.block_env.number = env.evm_env.block_env.number.saturating_add(1); } - env.block.basefee = U256::from(current_base_fee); - env.block.blob_excess_gas_and_price = current_excess_blob_gas_and_price; + env.evm_env.block_env.basefee = current_base_fee; + env.evm_env.block_env.blob_excess_gas_and_price = current_excess_blob_gas_and_price; // pick a random value for prevrandao - env.block.prevrandao = Some(B256::random()); + env.evm_env.block_env.prevrandao = Some(B256::random()); let best_hash = self.blockchain.storage.read().best_hash; @@ -1238,14 +1256,14 @@ impl Backend { // finally set the next block timestamp, this is done just before execution, because // there can be concurrent requests that can delay acquiring the db lock and we want // to ensure the timestamp is as close as possible to the actual execution. - env.block.timestamp = U256::from(self.time.next_timestamp()); + env.evm_env.block_env.timestamp = self.time.next_timestamp(); let executor = TransactionExecutor { db: &mut **db, validator: self, pending: pool_transactions.into_iter(), - block_env: env.block.clone(), - cfg_env: CfgEnvWithHandlerCfg::new(env.cfg.clone(), env.handler_cfg), + block_env: env.evm_env.block_env.clone(), + cfg_env: env.evm_env.cfg_env.clone(), parent_hash: best_hash, gas_used: 0, blob_gas_used: 0, @@ -1254,6 +1272,7 @@ impl Backend { print_traces: self.print_traces, odyssey: self.odyssey, precompile_factory: self.precompile_factory.clone(), + optimism: self.is_optimism(), }; let executed_tx = executor.execute(); @@ -1309,12 +1328,7 @@ impl Backend { } node_info!(""); - let mined_tx = MinedTransaction { - info, - receipt, - block_hash, - block_number: block_number.to::(), - }; + let mined_tx = MinedTransaction { info, receipt, block_hash, block_number }; storage.transactions.insert(mined_tx.info.transaction_hash, mined_tx); } @@ -1322,14 +1336,13 @@ impl Backend { if let Some(transaction_block_keeper) = self.transaction_block_keeper { if storage.blocks.len() > transaction_block_keeper { let to_clear = block_number - .to::() .saturating_sub(transaction_block_keeper.try_into().unwrap_or(u64::MAX)); storage.remove_block_transactions_by_number(to_clear) } } // we intentionally set the difficulty to `0` for newer blocks - env.block.difficulty = U256::from(0); + env.evm_env.block_env.difficulty = U256::from(0); // update env with new values *self.env.write() = env; @@ -1350,13 +1363,13 @@ impl Backend { (outcome, header, block_hash) }; let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas( - header.gas_used as u128, - header.gas_limit as u128, + header.gas_used, + header.gas_limit, header.base_fee_per_gas.unwrap_or_default(), ); let next_block_excess_blob_gas = self.fees.get_next_block_blob_excess_gas( - header.excess_blob_gas.map(|g| g as u128).unwrap_or_default(), - header.blob_gas_used.map(|g| g as u128).unwrap_or_default(), + header.excess_blob_gas.unwrap_or_default(), + header.blob_gas_used.unwrap_or_default(), ); // update next base fee @@ -1385,7 +1398,7 @@ impl Backend { overrides: Option, ) -> Result<(InstructionResult, Option, u128, State), BlockchainError> { self.with_database_at(block_request, |state, block| { - let block_number = block.number.to::(); + let block_number = block.number; let (exit, out, gas, state) = match overrides { None => self.call_with_state(state.as_dyn(), request, fee_details, block), Some(overrides) => { @@ -1404,13 +1417,13 @@ impl Backend { /// /// - `disable_eip3607` is set to `true` /// - `disable_base_fee` is set to `true` - /// - `nonce` is set to `None` + /// - `nonce` check is skipped if `request.nonce` is None fn build_call_env( &self, request: WithOtherFields, fee_details: FeeDetails, block_env: BlockEnv, - ) -> EnvWithHandlerCfg { + ) -> Env { let WithOtherFields:: { inner: TransactionRequest { @@ -1422,16 +1435,31 @@ impl Backend { access_list, blob_versioned_hashes, authorization_list, - // nonce is always ignored for calls - nonce: _, + nonce, sidecar: _, - chain_id: _, - transaction_type: _, + chain_id, + transaction_type, + max_fee_per_gas, + max_priority_fee_per_gas, .. // Rest of the gas fees related fields are taken from `fee_details` }, - .. + other, } = request; + let tx_type = transaction_type.unwrap_or_else(|| { + if authorization_list.is_some() { + EIP7702_TX_TYPE_ID + } else if blob_versioned_hashes.is_some() { + EIP4844_TX_TYPE_ID + } else if max_fee_per_gas.is_some() || max_priority_fee_per_gas.is_some() { + EIP1559_TX_TYPE_ID + } else if access_list.is_some() { + EIP2930_TX_TYPE_ID + } else { + LEGACY_TX_TYPE_ID + } + }); + let FeeDetails { gas_price, max_fee_per_gas, @@ -1439,19 +1467,19 @@ impl Backend { max_fee_per_blob_gas, } = fee_details; - let gas_limit = gas.unwrap_or(block_env.gas_limit.to()); + let gas_limit = gas.unwrap_or(block_env.gas_limit); let mut env = self.env.read().clone(); - env.block = block_env; + env.evm_env.block_env = block_env; // we want to disable this in eth_call, since this is common practice used by other node // impls and providers - env.cfg.disable_block_gas_limit = true; + env.evm_env.cfg_env.disable_block_gas_limit = true; // The basefee should be ignored for calls against state for // - eth_call // - eth_estimateGas // - eth_createAccessList // - tracing - env.cfg.disable_base_fee = true; + env.evm_env.cfg_env.disable_base_fee = true; let gas_price = gas_price.or(max_fee_per_gas).unwrap_or_else(|| { self.fees().raw_gas_price().saturating_add(MIN_SUGGESTED_PRIORITY_FEE) @@ -1459,48 +1487,75 @@ impl Backend { let caller = from.unwrap_or_default(); let to = to.as_ref().and_then(TxKind::to); let blob_hashes = blob_versioned_hashes.unwrap_or_default(); - env.tx = - TxEnv { + env.tx = OpTransaction { + base: TxEnv { caller, gas_limit, - gas_price: U256::from(gas_price), - gas_priority_fee: max_priority_fee_per_gas.map(U256::from), + gas_price, + gas_priority_fee: max_priority_fee_per_gas, max_fee_per_blob_gas: max_fee_per_blob_gas .or_else(|| { if !blob_hashes.is_empty() { - env.block.get_blob_gasprice() + env.evm_env.block_env.blob_gasprice() } else { - None + Some(0) } }) - .map(U256::from), - transact_to: match to { + .unwrap_or_default(), + kind: match to { Some(addr) => TxKind::Call(*addr), None => TxKind::Create, }, + tx_type, value: value.unwrap_or_default(), data: input.into_input().unwrap_or_default(), - chain_id: None, - // set nonce to None so that the correct nonce is chosen by the EVM - nonce: None, - access_list: access_list.unwrap_or_default().into(), + chain_id: Some(chain_id.unwrap_or(self.env.read().evm_env.cfg_env.chain_id)), + access_list: access_list.unwrap_or_default(), blob_hashes, - optimism: OptimismFields { enveloped_tx: Some(Bytes::new()), ..Default::default() }, - authorization_list: authorization_list.map(Into::into), - }; + authorization_list: authorization_list.unwrap_or_default(), + ..Default::default() + }, + ..Default::default() + }; - if env.block.basefee.is_zero() { + if let Some(nonce) = nonce { + env.tx.base.nonce = nonce; + } else { + // Disable nonce check in revm + env.evm_env.cfg_env.disable_nonce_check = true; + } + + if env.evm_env.block_env.basefee == 0 { // this is an edge case because the evm fails if `tx.effective_gas_price < base_fee` // 0 is only possible if it's manually set - env.cfg.disable_base_fee = true; + env.evm_env.cfg_env.disable_base_fee = true; + } + + // Deposit transaction? + if transaction_type == Some(DEPOSIT_TX_TYPE_ID) && has_optimism_fields(&other) { + let deposit = DepositTransactionParts { + source_hash: other + .get_deserialized::("sourceHash") + .map(|sh| sh.unwrap_or_default()) + .unwrap_or_default(), + mint: other + .get_deserialized::("mint") + .map(|m| m.unwrap_or_default()) + .or(None), + is_system_transaction: other + .get_deserialized::("isSystemTx") + .map(|st| st.unwrap_or_default()) + .unwrap_or_default(), + }; + env.tx.deposit = deposit; } env } /// Builds [`Inspector`] with the configured options. - fn build_inspector(&self) -> Inspector { - let mut inspector = Inspector::default(); + fn build_inspector(&self) -> AnvilInspector { + let mut inspector = AnvilInspector::default(); if self.print_logs { inspector = inspector.with_log_collector(); @@ -1551,13 +1606,13 @@ impl Backend { block_env.difficulty = difficulty; } if let Some(time) = overrides.time { - block_env.timestamp = U256::from(time); + block_env.timestamp = time; } if let Some(gas_limit) = overrides.gas_limit { - block_env.gas_limit = U256::from(gas_limit); + block_env.gas_limit = gas_limit; } if let Some(coinbase) = overrides.coinbase { - block_env.coinbase = coinbase; + block_env.beneficiary = coinbase; } if let Some(random) = overrides.random { block_env.prevrandao = Some(random); @@ -1584,11 +1639,11 @@ impl Backend { ); // Always disable EIP-3607 - env.cfg.disable_eip3607 = true; + env.evm_env.cfg_env.disable_eip3607 = true; if !validation { - env.cfg.disable_base_fee = !validation; - env.block.basefee = U256::from(0); + env.evm_env.cfg_env.disable_base_fee = !validation; + env.evm_env.block_env.basefee = 0; } // transact @@ -1596,16 +1651,23 @@ impl Backend { // prepare inspector to capture transfer inside the evm so they are // recorded and included in logs let mut inspector = TransferInspector::new(false).with_logs(true); - let mut evm = - self.new_evm_with_inspector_ref(cache_db.as_dyn(), env, &mut inspector); - trace!(target: "backend", env=?evm.context.env(), spec=?evm.spec_id(), "simulate evm env"); - evm.transact()? + let mut evm= self.new_evm_with_inspector_ref( + cache_db.as_dyn(), + &env, + &mut inspector, + ); + + trace!(target: "backend", env=?env.evm_env, spec=?env.evm_env.spec_id(),"simulate evm env"); + evm.transact(env.tx)? } else { let mut inspector = self.build_inspector(); - let mut evm = - self.new_evm_with_inspector_ref(cache_db.as_dyn(), env, &mut inspector); - trace!(target: "backend", env=?evm.context.env(),spec=?evm.spec_id(), "simulate evm env"); - evm.transact()? + let mut evm = self.new_evm_with_inspector_ref( + cache_db.as_dyn(), + &env, + &mut inspector, + ); + trace!(target: "backend", env=?env.evm_env, spec=?env.evm_env.spec_id(),"simulate evm env"); + evm.transact(env.tx)? }; trace!(target: "backend", ?result, ?request, "simulate call"); @@ -1627,7 +1689,7 @@ impl Backend { MaybeImpersonatedTransaction::impersonated(tx, from), None, None, - Some(block_env.basefee.to()), + Some(block_env.basefee), ); transactions.push(rpc_tx); @@ -1648,8 +1710,8 @@ impl Backend { .enumerate() .map(|(idx, log)| Log { inner: log, - block_number: Some(block_env.number.to()), - block_timestamp: Some(block_env.timestamp.to()), + block_number: Some(block_env.number), + block_timestamp: Some(block_env.timestamp), transaction_index: Some(req_idx as u64), log_index: Some((idx + log_index) as u64), removed: false, @@ -1679,17 +1741,17 @@ impl Backend { receipts_root: calculate_receipt_root(&transactions_envelopes), parent_hash: Default::default(), ommers_hash: Default::default(), - beneficiary: block_env.coinbase, + beneficiary: block_env.beneficiary, state_root: Default::default(), difficulty: Default::default(), - number: block_env.number.to(), - gas_limit: block_env.gas_limit.to(), + number: block_env.number, + gas_limit: block_env.gas_limit, gas_used, - timestamp: block_env.timestamp.to(), + timestamp: block_env.timestamp, extra_data: Default::default(), mix_hash: Default::default(), nonce: Default::default(), - base_fee_per_gas: Some(block_env.basefee.to()), + base_fee_per_gas: Some(block_env.basefee), withdrawals_root: None, blob_gas_used: None, excess_blob_gas: None, @@ -1718,15 +1780,13 @@ impl Backend { }; // update block env - block_env.number += U256::from(1); - block_env.timestamp += U256::from(12); - block_env.basefee = U256::from( - simulated_block - .inner - .header - .next_block_base_fee(BaseFeeParams::ethereum()) - .unwrap_or_default(), - ); + block_env.number += 1; + block_env.timestamp += 12; + block_env.basefee = simulated_block + .inner + .header + .next_block_base_fee(BaseFeeParams::ethereum()) + .unwrap_or_default(); block_res.push(simulated_block); } @@ -1746,8 +1806,8 @@ impl Backend { let mut inspector = self.build_inspector(); let env = self.build_call_env(request, fee_details, block_env); - let mut evm = self.new_evm_with_inspector_ref(state, env, &mut inspector); - let ResultAndState { result, state } = evm.transact()?; + let mut evm = self.new_evm_with_inspector_ref(state, &env, &mut inspector); + let ResultAndState { result, state } = evm.transact(env.tx)?; let (exit_reason, gas_used, out) = match result { ExecutionResult::Success { reason, gas_used, output, .. } => { (reason.into(), gas_used, Some(output)) @@ -1755,7 +1815,9 @@ impl Backend { ExecutionResult::Revert { gas_used, output } => { (InstructionResult::Revert, gas_used, Some(Output::Call(output))) } - ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None), + ExecutionResult::Halt { reason, gas_used } => { + (op_haltreason_to_instruction_result(reason), gas_used, None) + } }; drop(evm); inspector.print_logs(); @@ -1803,10 +1865,10 @@ impl Backend { let env = self.build_call_env(request, fee_details, block); let mut evm = self.new_evm_with_inspector_ref( state.as_dyn(), - env, + &env, &mut inspector, ); - let ResultAndState { result, state: _ } = evm.transact()?; + let ResultAndState { result, state: _ } = evm.transact(env.tx)?; drop(evm); let tracing_inspector = inspector.tracer.expect("tracer disappeared"); @@ -1837,8 +1899,8 @@ impl Backend { .with_tracing_config(TracingInspectorConfig::from_geth_config(&config)); let env = self.build_call_env(request, fee_details, block); - let mut evm = self.new_evm_with_inspector_ref(state.as_dyn(), env, &mut inspector); - let ResultAndState { result, state: _ } = evm.transact()?; + let mut evm = self.new_evm_with_inspector_ref(state.as_dyn(), &env, &mut inspector); + let ResultAndState { result, state: _ } = evm.transact(env.tx)?; let (exit_reason, gas_used, out) = match result { ExecutionResult::Success { reason, gas_used, output, .. } => { @@ -1847,7 +1909,9 @@ impl Backend { ExecutionResult::Revert { gas_used, output } => { (InstructionResult::Revert, gas_used, Some(Output::Call(output))) } - ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None), + ExecutionResult::Halt { reason, gas_used } => { + (op_haltreason_to_instruction_result(reason), gas_used, None) + } }; drop(evm); @@ -1877,8 +1941,8 @@ impl Backend { AccessListInspector::new(request.access_list.clone().unwrap_or_default()); let env = self.build_call_env(request, fee_details, block_env); - let mut evm = self.new_evm_with_inspector_ref(state, env, &mut inspector); - let ResultAndState { result, state: _ } = evm.transact()?; + let mut evm = self.new_evm_with_inspector_ref(state, &env, &mut inspector); + let ResultAndState { result, state: _ } = evm.transact(env.tx)?; let (exit_reason, gas_used, out) = match result { ExecutionResult::Success { reason, gas_used, output, .. } => { (reason.into(), gas_used, Some(output)) @@ -1886,7 +1950,9 @@ impl Backend { ExecutionResult::Revert { gas_used, output } => { (InstructionResult::Revert, gas_used, Some(Output::Call(output))) } - ExecutionResult::Halt { reason, gas_used } => (reason.into(), gas_used, None), + ExecutionResult::Halt { reason, gas_used } => { + (op_haltreason_to_instruction_result(reason), gas_used, None) + } }; drop(evm); let access_list = inspector.access_list(); @@ -2136,12 +2202,12 @@ impl Backend { BlockId::Hash(hash) => hash.block_hash, BlockId::Number(number) => { let storage = self.blockchain.storage.read(); - let slots_in_an_epoch = U64::from(self.slots_in_an_epoch); + let slots_in_an_epoch = self.slots_in_an_epoch; match number { BlockNumber::Latest => storage.best_hash, BlockNumber::Earliest => storage.genesis_hash, BlockNumber::Pending => return None, - BlockNumber::Number(num) => *storage.hashes.get(&U64::from(num))?, + BlockNumber::Number(num) => *storage.hashes.get(&num)?, BlockNumber::Safe => { if storage.best_number > (slots_in_an_epoch) { *storage.hashes.get(&(storage.best_number - (slots_in_an_epoch)))? @@ -2150,10 +2216,8 @@ impl Backend { } } BlockNumber::Finalized => { - if storage.best_number > (slots_in_an_epoch * U64::from(2)) { - *storage - .hashes - .get(&(storage.best_number - (slots_in_an_epoch * U64::from(2))))? + if storage.best_number > (slots_in_an_epoch * 2) { + *storage.hashes.get(&(storage.best_number - (slots_in_an_epoch * 2)))? } else { storage.genesis_hash } @@ -2210,7 +2274,7 @@ impl Backend { let mut block = WithOtherFields::new(block); // If Arbitrum, apply chain specifics to converted block. - if is_arbitrum(self.env.read().cfg.chain_id) { + if is_arbitrum(self.env.read().evm_env.cfg_env.chain_id) { // Set `l1BlockNumber` field. block.other.insert("l1BlockNumber".to_string(), number.into()); } @@ -2279,13 +2343,13 @@ impl Backend { .with_pending_block(pool_transactions, |state, block| { let block = block.block; let block = BlockEnv { - number: U256::from(block.header.number), - coinbase: block.header.beneficiary, - timestamp: U256::from(block.header.timestamp), + number: block.header.number, + beneficiary: block.header.beneficiary, + timestamp: block.header.timestamp, difficulty: block.header.difficulty, prevrandao: Some(block.header.mix_hash), - basefee: U256::from(block.header.base_fee_per_gas.unwrap_or_default()), - gas_limit: U256::from(block.header.gas_limit), + basefee: block.header.base_fee_per_gas.unwrap_or_default(), + gas_limit: block.header.gas_limit, ..Default::default() }; f(state, block) @@ -2296,23 +2360,23 @@ impl Backend { Some(BlockRequest::Number(bn)) => Some(BlockNumber::Number(bn)), None => None, }; - let block_number: U256 = U256::from(self.convert_block_number(block_number)); + let block_number = self.convert_block_number(block_number); - if block_number < self.env.read().block.number { + if block_number < self.env.read().evm_env.block_env.number { if let Some((block_hash, block)) = self - .block_by_number(BlockNumber::Number(block_number.to::())) + .block_by_number(BlockNumber::Number(block_number)) .await? .map(|block| (block.header.hash, block)) { if let Some(state) = self.states.write().get(&block_hash) { let block = BlockEnv { number: block_number, - coinbase: block.header.beneficiary, - timestamp: U256::from(block.header.timestamp), + beneficiary: block.header.beneficiary, + timestamp: block.header.timestamp, difficulty: block.header.difficulty, prevrandao: block.header.mix_hash, - basefee: U256::from(block.header.base_fee_per_gas.unwrap_or_default()), - gas_limit: U256::from(block.header.gas_limit), + basefee: block.header.base_fee_per_gas.unwrap_or_default(), + gas_limit: block.header.gas_limit, ..Default::default() }; return Ok(f(Box::new(state), block)); @@ -2321,13 +2385,13 @@ impl Backend { warn!(target: "backend", "Not historic state found for block={}", block_number); return Err(BlockchainError::BlockOutOfRange( - self.env.read().block.number.to::(), - block_number.to::(), + self.env.read().evm_env.block_env.number, + block_number, )); } let db = self.db.read().await; - let block = self.env.read().block.clone(); + let block = self.env.read().evm_env.block_env.clone(); Ok(f(Box::new(&**db), block)) } @@ -2976,13 +3040,13 @@ impl Backend { // Set environment back to common block let mut env = self.env.write(); - env.block.number = U256::from(common_block.header.number); - env.block.timestamp = U256::from(common_block.header.timestamp); - env.block.gas_limit = U256::from(common_block.header.gas_limit); - env.block.difficulty = common_block.header.difficulty; - env.block.prevrandao = Some(common_block.header.mix_hash); + env.evm_env.block_env.number = common_block.header.number; + env.evm_env.block_env.timestamp = common_block.header.timestamp; + env.evm_env.block_env.gas_limit = common_block.header.gas_limit; + env.evm_env.block_env.difficulty = common_block.header.difficulty; + env.evm_env.block_env.prevrandao = Some(common_block.header.mix_hash); - self.time.reset(env.block.timestamp.to::()); + self.time.reset(env.evm_env.block_env.timestamp); } Ok(()) } @@ -3021,7 +3085,7 @@ impl TransactionValidator for Backend { &self, pending: &PendingTransaction, account: &AccountInfo, - env: &EnvWithHandlerCfg, + env: &Env, ) -> Result<(), InvalidTransactionError> { let tx = &pending.transaction; @@ -3030,7 +3094,7 @@ impl TransactionValidator for Backend { if chain_id.to::() != tx_chain_id { if let Some(legacy) = tx.as_legacy() { // - if env.handler_cfg.spec_id >= SpecId::SPURIOUS_DRAGON && + if env.evm_env.cfg_env.spec >= SpecId::SPURIOUS_DRAGON && legacy.tx().chain_id.is_none() { warn!(target: "backend", ?chain_id, ?tx_chain_id, "incompatible EIP155-based V"); @@ -3049,7 +3113,9 @@ impl TransactionValidator for Backend { } // Check gas limit, iff block gas limit is set. - if !env.cfg.disable_block_gas_limit && tx.gas_limit() > env.block.gas_limit.to::() { + if !env.evm_env.cfg_env.disable_block_gas_limit && + tx.gas_limit() > env.evm_env.block_env.gas_limit + { warn!(target: "backend", "[{:?}] gas too high", tx.hash()); return Err(InvalidTransactionError::GasTooHigh(ErrDetail { detail: String::from("tx.gas_limit > env.block.gas_limit"), @@ -3065,9 +3131,9 @@ impl TransactionValidator for Backend { return Err(InvalidTransactionError::NonceTooLow); } - if (env.handler_cfg.spec_id as u8) >= (SpecId::LONDON as u8) { - if tx.gas_price() < env.block.basefee.to::() && !is_deposit_tx { - warn!(target: "backend", "max fee per gas={}, too low, block basefee={}",tx.gas_price(), env.block.basefee); + if env.evm_env.cfg_env.spec >= SpecId::LONDON { + if tx.gas_price() < env.evm_env.block_env.basefee.into() && !is_deposit_tx { + warn!(target: "backend", "max fee per gas={}, too low, block basefee={}",tx.gas_price(), env.evm_env.block_env.basefee); return Err(InvalidTransactionError::FeeCapTooLow); } @@ -3082,10 +3148,10 @@ impl TransactionValidator for Backend { } // EIP-4844 Cancun hard fork validation steps - if env.spec_id() >= SpecId::CANCUN && tx.transaction.is_eip4844() { + if env.evm_env.cfg_env.spec >= SpecId::CANCUN && tx.transaction.is_eip4844() { // Light checks first: see if the blob fee cap is too low. if let Some(max_fee_per_blob_gas) = tx.essentials().max_fee_per_blob_gas { - if let Some(blob_gas_and_price) = &env.block.blob_excess_gas_and_price { + if let Some(blob_gas_and_price) = &env.evm_env.block_env.blob_excess_gas_and_price { if max_fee_per_blob_gas < blob_gas_and_price.blob_gasprice { warn!(target: "backend", "max fee per blob gas={}, too low, block blob gas price={}", max_fee_per_blob_gas, blob_gas_and_price.blob_gasprice); return Err(InvalidTransactionError::BlobFeeCapTooLow); @@ -3108,12 +3174,12 @@ impl TransactionValidator for Backend { // Ensure the tx does not exceed the max blobs per block. if blob_count > MAX_BLOBS_PER_BLOCK { - return Err(InvalidTransactionError::TooManyBlobs(blob_count)) + return Err(InvalidTransactionError::TooManyBlobs(blob_count, MAX_BLOBS_PER_BLOCK)) } // Check for any blob validation errors if not impersonating. if !self.skip_blob_validation(Some(*pending.sender())) { - if let Err(err) = tx.validate(env.cfg.kzg_settings.get()) { + if let Err(err) = tx.validate(EnvKzgSettings::default().get()) { return Err(InvalidTransactionError::BlobTransactionValidationError(err)) } } @@ -3154,7 +3220,7 @@ impl TransactionValidator for Backend { &self, tx: &PendingTransaction, account: &AccountInfo, - env: &EnvWithHandlerCfg, + env: &Env, ) -> Result<(), InvalidTransactionError> { self.validate_pool_transaction_for(tx, account, env)?; if tx.nonce() > account.nonce { @@ -3347,3 +3413,10 @@ pub fn is_arbitrum(chain_id: u64) -> bool { } false } + +pub fn op_haltreason_to_instruction_result(op_reason: OpHaltReason) -> InstructionResult { + match op_reason { + OpHaltReason::Base(eth_h) => eth_h.into(), + OpHaltReason::FailedDeposit => InstructionResult::Stop, + } +} diff --git a/crates/anvil/src/eth/backend/mem/state.rs b/crates/anvil/src/eth/backend/mem/state.rs index aea154a7bd573..33db0b746a316 100644 --- a/crates/anvil/src/eth/backend/mem/state.rs +++ b/crates/anvil/src/eth/backend/mem/state.rs @@ -1,16 +1,15 @@ //! Support for generating the state root for memdb storage use crate::eth::error::BlockchainError; -use alloy_primitives::{keccak256, Address, B256, U256}; +use alloy_primitives::{keccak256, map::HashMap, Address, B256, U256}; use alloy_rlp::Encodable; use alloy_rpc_types::state::StateOverride; use alloy_trie::{HashBuilder, Nibbles}; -use foundry_evm::{ - backend::DatabaseError, - revm::{ - db::{CacheDB, DatabaseRef, DbAccount}, - primitives::{AccountInfo, Bytecode, HashMap}, - }, +use foundry_evm::backend::DatabaseError; +use revm::{ + bytecode::Bytecode, + database::{CacheDB, DatabaseRef, DbAccount}, + state::AccountInfo, }; pub fn build_root(values: impl IntoIterator)>) -> B256 { diff --git a/crates/anvil/src/eth/backend/mem/storage.rs b/crates/anvil/src/eth/backend/mem/storage.rs index e024d97505467..7c2695fa275fb 100644 --- a/crates/anvil/src/eth/backend/mem/storage.rs +++ b/crates/anvil/src/eth/backend/mem/storage.rs @@ -5,6 +5,7 @@ use crate::eth::{ MaybeFullDatabase, SerializableBlock, SerializableHistoricalStates, SerializableTransaction, StateDb, }, + env::Env, mem::cache::DiskStateCache, }, error::BlockchainError, @@ -14,7 +15,7 @@ use alloy_consensus::constants::EMPTY_WITHDRAWALS; use alloy_eips::eip7685::EMPTY_REQUESTS_HASH; use alloy_primitives::{ map::{B256HashMap, HashMap}, - Bytes, B256, U256, U64, + Bytes, B256, U256, }; use alloy_rpc_types::{ trace::{ @@ -34,13 +35,12 @@ use anvil_core::eth::{ use anvil_rpc::error::RpcError; use foundry_evm::{ backend::MemDb, - revm::primitives::Env, traces::{ CallKind, FourByteInspector, GethTraceBuilder, ParityTraceBuilder, TracingInspectorConfig, }, }; use parking_lot::RwLock; -use revm::primitives::SpecId; +use revm::{context::Block as RevmBlock, primitives::hardfork::SpecId}; use std::{collections::VecDeque, fmt, path::PathBuf, sync::Arc, time::Duration}; // use yansi::Paint; @@ -255,11 +255,11 @@ pub struct BlockchainStorage { /// all stored blocks (block hash -> block) pub blocks: B256HashMap, /// mapping from block number -> block hash - pub hashes: HashMap, + pub hashes: HashMap, /// The current best hash pub best_hash: B256, /// The current best block number - pub best_number: U64, + pub best_number: u64, /// genesis hash of the chain pub genesis_hash: B256, /// Mapping from the transaction hash to a tuple containing the transaction as well as the @@ -286,11 +286,11 @@ impl BlockchainStorage { let partial_header = PartialHeader { timestamp, base_fee, - gas_limit: env.block.gas_limit.to::(), - beneficiary: env.block.coinbase, - difficulty: env.block.difficulty, - blob_gas_used: env.block.blob_excess_gas_and_price.as_ref().map(|_| 0), - excess_blob_gas: env.block.get_blob_excess_gas(), + gas_limit: env.evm_env.block_env.gas_limit, + beneficiary: env.evm_env.block_env.beneficiary, + difficulty: env.evm_env.block_env.difficulty, + blob_gas_used: env.evm_env.block_env.blob_excess_gas_and_price.as_ref().map(|_| 0), + excess_blob_gas: env.evm_env.block_env.blob_excess_gas(), number: genesis_number, parent_beacon_block_root: is_cancun.then_some(Default::default()), withdrawals_root: is_shanghai.then_some(EMPTY_WITHDRAWALS), @@ -300,7 +300,7 @@ impl BlockchainStorage { let block = Block::new::(partial_header, vec![]); let genesis_hash = block.header.hash_slow(); let best_hash = genesis_hash; - let best_number: U64 = U64::from(genesis_number); + let best_number = genesis_number; let mut blocks = B256HashMap::default(); blocks.insert(genesis_hash, block); @@ -320,13 +320,13 @@ impl BlockchainStorage { pub fn forked(block_number: u64, block_hash: B256, total_difficulty: U256) -> Self { let mut hashes = HashMap::default(); - hashes.insert(U64::from(block_number), block_hash); + hashes.insert(block_number, block_hash); Self { blocks: B256HashMap::default(), hashes, best_hash: block_hash, - best_number: U64::from(block_number), + best_number: block_number, genesis_hash: Default::default(), transactions: Default::default(), total_difficulty, @@ -338,16 +338,16 @@ impl BlockchainStorage { /// The block identified by `block_number` and `block_hash` is __non-inclusive__, i.e. it will /// remain in the state. pub fn unwind_to(&mut self, block_number: u64, block_hash: B256) { - let best_num: u64 = self.best_number.try_into().unwrap_or(0); + let best_num: u64 = self.best_number; for i in (block_number + 1)..=best_num { - if let Some(hash) = self.hashes.remove(&U64::from(i)) { + if let Some(hash) = self.hashes.remove(&i) { if let Some(block) = self.blocks.remove(&hash) { self.remove_block_transactions_by_number(block.header.number); } } } self.best_hash = block_hash; - self.best_number = U64::from(block_number); + self.best_number = block_number; } pub fn empty() -> Self { @@ -364,7 +364,7 @@ impl BlockchainStorage { /// Removes all stored transactions for the given block number pub fn remove_block_transactions_by_number(&mut self, num: u64) { - if let Some(hash) = self.hashes.get(&(U64::from(num))).copied() { + if let Some(hash) = self.hashes.get(&num).copied() { self.remove_block_transactions(hash); } } @@ -383,12 +383,12 @@ impl BlockchainStorage { impl BlockchainStorage { /// Returns the hash for [BlockNumberOrTag] pub fn hash(&self, number: BlockNumberOrTag) -> Option { - let slots_in_an_epoch = U64::from(32u64); + let slots_in_an_epoch = 32; match number { BlockNumberOrTag::Latest => Some(self.best_hash), BlockNumberOrTag::Earliest => Some(self.genesis_hash), BlockNumberOrTag::Pending => None, - BlockNumberOrTag::Number(num) => self.hashes.get(&U64::from(num)).copied(), + BlockNumberOrTag::Number(num) => self.hashes.get(&num).copied(), BlockNumberOrTag::Safe => { if self.best_number > (slots_in_an_epoch) { self.hashes.get(&(self.best_number - (slots_in_an_epoch))).copied() @@ -397,10 +397,8 @@ impl BlockchainStorage { } } BlockNumberOrTag::Finalized => { - if self.best_number > (slots_in_an_epoch * U64::from(2)) { - self.hashes - .get(&(self.best_number - (slots_in_an_epoch * U64::from(2)))) - .copied() + if self.best_number > (slots_in_an_epoch * 2) { + self.hashes.get(&(self.best_number - (slots_in_an_epoch * 2))).copied() } else { Some(self.genesis_hash) } @@ -423,7 +421,7 @@ impl BlockchainStorage { let block_hash = block.header.hash_slow(); let block_number = block.header.number; self.blocks.insert(block_hash, block); - self.hashes.insert(U64::from(block_number), block_hash); + self.hashes.insert(block_number, block_hash); } } @@ -499,7 +497,7 @@ impl Blockchain { #[derive(Clone, Debug)] pub struct MinedBlockOutcome { /// The block that was mined - pub block_number: U64, + pub block_number: u64, /// All transactions included in the block pub included: Vec>, /// All transactions that were attempted to be included but were invalid at the time of @@ -611,16 +609,11 @@ pub struct MinedTransactionReceipt { mod tests { use super::*; use crate::eth::backend::db::Db; - use alloy_primitives::{hex, Address}; + use alloy_primitives::{hex, Address, U256}; use alloy_rlp::Decodable; use anvil_core::eth::transaction::TypedTransaction; - use foundry_evm::{ - backend::MemDb, - revm::{ - db::DatabaseRef, - primitives::{AccountInfo, U256}, - }, - }; + use foundry_evm::backend::MemDb; + use revm::{database::DatabaseRef, state::AccountInfo}; #[test] fn test_interval_update() { diff --git a/crates/anvil/src/eth/backend/mod.rs b/crates/anvil/src/eth/backend/mod.rs index 48b08e07cd1ec..be2c90b576800 100644 --- a/crates/anvil/src/eth/backend/mod.rs +++ b/crates/anvil/src/eth/backend/mod.rs @@ -8,6 +8,7 @@ pub mod mem; pub mod cheats; pub mod time; +pub mod env; pub mod executor; pub mod fork; pub mod genesis; diff --git a/crates/anvil/src/eth/backend/validate.rs b/crates/anvil/src/eth/backend/validate.rs index eca3fd9e3bfe9..0a22ea5f5a880 100644 --- a/crates/anvil/src/eth/backend/validate.rs +++ b/crates/anvil/src/eth/backend/validate.rs @@ -1,8 +1,11 @@ //! Support for validating transactions at certain stages -use crate::eth::error::{BlockchainError, InvalidTransactionError}; +use crate::eth::{ + backend::env::Env, + error::{BlockchainError, InvalidTransactionError}, +}; use anvil_core::eth::transaction::PendingTransaction; -use foundry_evm::revm::primitives::{AccountInfo, EnvWithHandlerCfg}; +use revm::state::AccountInfo; /// A trait for validating transactions #[async_trait::async_trait] @@ -21,7 +24,7 @@ pub trait TransactionValidator { &self, tx: &PendingTransaction, account: &AccountInfo, - env: &EnvWithHandlerCfg, + env: &Env, ) -> Result<(), InvalidTransactionError>; /// Validates the transaction against a specific account @@ -31,6 +34,6 @@ pub trait TransactionValidator { &self, tx: &PendingTransaction, account: &AccountInfo, - env: &EnvWithHandlerCfg, + env: &Env, ) -> Result<(), InvalidTransactionError>; } diff --git a/crates/anvil/src/eth/error.rs b/crates/anvil/src/eth/error.rs index 6666f8021dcfe..f9343d520ecfa 100644 --- a/crates/anvil/src/eth/error.rs +++ b/crates/anvil/src/eth/error.rs @@ -10,13 +10,11 @@ use anvil_rpc::{ error::{ErrorCode, RpcError}, response::ResponseResult, }; -use foundry_evm::{ - backend::DatabaseError, - decode::RevertDecoder, - revm::{ - interpreter::InstructionResult, - primitives::{EVMError, InvalidHeader}, - }, +use foundry_evm::{backend::DatabaseError, decode::RevertDecoder}; +use op_revm::OpTransactionError; +use revm::{ + context_interface::result::{EVMError, InvalidHeader, InvalidTransaction}, + interpreter::InstructionResult, }; use serde::Serialize; @@ -122,7 +120,31 @@ where InvalidHeader::PrevrandaoNotSet => Self::PrevrandaoNotSet, }, EVMError::Database(err) => err.into(), - EVMError::Precompile(err) => Self::Message(err), + EVMError::Custom(err) => Self::Message(err), + } + } +} + +impl From> for BlockchainError +where + T: Into, +{ + fn from(err: EVMError) -> Self { + match err { + EVMError::Transaction(err) => match err { + OpTransactionError::Base(err) => InvalidTransactionError::from(err).into(), + OpTransactionError::DepositSystemTxPostRegolith => { + Self::DepositTransactionUnsupported + } + OpTransactionError::HaltedDepositPostRegolith => { + Self::DepositTransactionUnsupported + } + }, + EVMError::Header(err) => match err { + InvalidHeader::ExcessBlobGasNotSet => Self::ExcessBlobGasNotSet, + InvalidHeader::PrevrandaoNotSet => Self::PrevrandaoNotSet, + }, + EVMError::Database(err) => err.into(), EVMError::Custom(err) => Self::Message(err), } } @@ -246,8 +268,8 @@ pub enum InvalidTransactionError { /// Thrown when there are no `blob_hashes` in the transaction, and it is an EIP-4844 tx. #[error("`blob_hashes` are required for EIP-4844 transactions")] NoBlobHashes, - #[error("too many blobs in one transaction, have: {0}")] - TooManyBlobs(usize), + #[error("too many blobs in one transaction, have: {0}, max: {1}")] + TooManyBlobs(usize, usize), /// Thrown when there's a blob validation error #[error(transparent)] BlobTransactionValidationError(#[from] alloy_consensus::BlobTransactionValidationError), @@ -265,12 +287,14 @@ pub enum InvalidTransactionError { AuthorizationListNotSupported, /// Forwards error from the revm #[error(transparent)] - Revm(revm::primitives::InvalidTransaction), + Revm(revm::context_interface::result::InvalidTransaction), + /// Deposit transaction error post regolith + #[error("op-deposit failure post regolith")] + DepositTxErrorPostRegolith, } -impl From for InvalidTransactionError { - fn from(err: revm::primitives::InvalidTransaction) -> Self { - use revm::primitives::InvalidTransaction; +impl From for InvalidTransactionError { + fn from(err: InvalidTransaction) -> Self { match err { InvalidTransaction::InvalidChainId => Self::InvalidChainId, InvalidTransaction::PriorityFeeGreaterThanMaxFee => Self::TipAboveFeeCap, @@ -278,10 +302,10 @@ impl From for InvalidTransactionError { InvalidTransaction::CallerGasLimitMoreThanBlock => { Self::GasTooHigh(ErrDetail { detail: String::from("CallerGasLimitMoreThanBlock") }) } - InvalidTransaction::CallGasCostMoreThanGasLimit => { + InvalidTransaction::CallGasCostMoreThanGasLimit { .. } => { Self::GasTooHigh(ErrDetail { detail: String::from("CallGasCostMoreThanGasLimit") }) } - InvalidTransaction::GasFloorMoreThanGasLimit => { + InvalidTransaction::GasFloorMoreThanGasLimit { .. } => { Self::GasTooHigh(ErrDetail { detail: String::from("CallGasCostMoreThanGasLimit") }) } InvalidTransaction::RejectCallerWithCode => Self::SenderNoEOA, @@ -300,18 +324,30 @@ impl From for InvalidTransactionError { InvalidTransaction::BlobCreateTransaction => Self::BlobCreateTransaction, InvalidTransaction::BlobVersionNotSupported => Self::BlobVersionNotSupported, InvalidTransaction::EmptyBlobs => Self::EmptyBlobs, - InvalidTransaction::TooManyBlobs { have } => Self::TooManyBlobs(have), + InvalidTransaction::TooManyBlobs { have, max } => Self::TooManyBlobs(have, max), InvalidTransaction::AuthorizationListNotSupported => { Self::AuthorizationListNotSupported } InvalidTransaction::AuthorizationListInvalidFields | - InvalidTransaction::OptimismError(_) | - InvalidTransaction::EofCrateShouldHaveToAddress | + InvalidTransaction::Eip1559NotSupported | + InvalidTransaction::Eip2930NotSupported | + InvalidTransaction::Eip4844NotSupported | + InvalidTransaction::Eip7702NotSupported | + InvalidTransaction::EofCreateShouldHaveToAddress | InvalidTransaction::EmptyAuthorizationList => Self::Revm(err), } } } +impl From for InvalidTransactionError { + fn from(value: OpTransactionError) -> Self { + match value { + OpTransactionError::Base(err) => err.into(), + OpTransactionError::DepositSystemTxPostRegolith | + OpTransactionError::HaltedDepositPostRegolith => Self::DepositTxErrorPostRegolith, + } + } +} /// Helper trait to easily convert results to rpc results pub(crate) trait ToRpcResponseResult { fn to_rpc_result(self) -> ResponseResult; diff --git a/crates/anvil/src/eth/fees.rs b/crates/anvil/src/eth/fees.rs index bb405f62d1ef1..bb9272f5f41c4 100644 --- a/crates/anvil/src/eth/fees.rs +++ b/crates/anvil/src/eth/fees.rs @@ -1,7 +1,12 @@ -use crate::eth::{ - backend::{info::StorageInfo, notifications::NewBlockNotifications}, - error::BlockchainError, +use std::{ + collections::BTreeMap, + fmt, + future::Future, + pin::Pin, + sync::Arc, + task::{Context, Poll}, }; + use alloy_consensus::Header; use alloy_eips::{ calc_next_block_base_fee, eip1559::BaseFeeParams, eip4844::MAX_DATA_GAS_PER_BLOCK, @@ -9,16 +14,13 @@ use alloy_eips::{ }; use alloy_primitives::B256; use anvil_core::eth::transaction::TypedTransaction; -use foundry_evm::revm::primitives::{BlobExcessGasAndPrice, SpecId}; use futures::StreamExt; use parking_lot::{Mutex, RwLock}; -use std::{ - collections::BTreeMap, - fmt, - future::Future, - pin::Pin, - sync::Arc, - task::{Context, Poll}, +use revm::{context_interface::block::BlobExcessGasAndPrice, primitives::hardfork::SpecId}; + +use crate::eth::{ + backend::{info::StorageInfo, notifications::NewBlockNotifications}, + error::BlockchainError, }; /// Maximum number of entries in the fee history cache @@ -54,7 +56,7 @@ pub struct FeeManager { /// Tracks the excess blob gas, and the base fee, for the next block post Cancun /// /// This value will be updated after a new block was mined - blob_excess_gas_and_price: Arc>, + blob_excess_gas_and_price: Arc>, /// The base price to use Pre London /// /// This will be constant value unless changed manually @@ -121,7 +123,7 @@ impl FeeManager { pub fn excess_blob_gas_and_price(&self) -> Option { if self.is_eip4844() { - Some(self.blob_excess_gas_and_price.read().clone()) + Some(*self.blob_excess_gas_and_price.read()) } else { None } @@ -158,8 +160,8 @@ impl FeeManager { /// Calculates the base fee for the next block pub fn get_next_block_base_fee_per_gas( &self, - gas_used: u128, - gas_limit: u128, + gas_used: u64, + gas_limit: u64, last_fee_per_gas: u64, ) -> u64 { // It's naturally impossible for base fee to be 0; @@ -178,18 +180,14 @@ impl FeeManager { /// Calculates the next block blob excess gas, using the provided parent blob gas used and /// parent blob excess gas - pub fn get_next_block_blob_excess_gas( - &self, - blob_gas_used: u128, - blob_excess_gas: u128, - ) -> u64 { - alloy_eips::eip4844::calc_excess_blob_gas(blob_gas_used as u64, blob_excess_gas as u64) + pub fn get_next_block_blob_excess_gas(&self, blob_gas_used: u64, blob_excess_gas: u64) -> u64 { + alloy_eips::eip4844::calc_excess_blob_gas(blob_gas_used, blob_excess_gas) } } /// Calculate base fee for next block. [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec -pub fn calculate_next_block_base_fee(gas_used: u128, gas_limit: u128, base_fee: u64) -> u64 { - calc_next_block_base_fee(gas_used as u64, gas_limit as u64, base_fee, BaseFeeParams::ethereum()) +pub fn calculate_next_block_base_fee(gas_used: u64, gas_limit: u64, base_fee: u64) -> u64 { + calc_next_block_base_fee(gas_used, gas_limit, base_fee, BaseFeeParams::ethereum()) } /// An async service that takes care of the `FeeHistory` cache diff --git a/crates/anvil/src/eth/pool/mod.rs b/crates/anvil/src/eth/pool/mod.rs index 544d7eac9df37..2133ea083df24 100644 --- a/crates/anvil/src/eth/pool/mod.rs +++ b/crates/anvil/src/eth/pool/mod.rs @@ -36,7 +36,7 @@ use crate::{ }, mem::storage::MinedBlockOutcome, }; -use alloy_primitives::{Address, TxHash, U64}; +use alloy_primitives::{Address, TxHash}; use alloy_rpc_types::txpool::TxpoolStatus; use anvil_core::eth::transaction::PendingTransaction; use futures::channel::mpsc::{channel, Receiver, Sender}; @@ -102,7 +102,7 @@ impl Pool { /// directly or are a dependency of the transaction associated with that marker. pub fn prune_markers( &self, - block_number: U64, + block_number: u64, markers: impl IntoIterator, ) -> PruneResult { debug!(target: "txpool", ?block_number, "pruning transactions"); diff --git a/crates/anvil/src/eth/pool/transactions.rs b/crates/anvil/src/eth/pool/transactions.rs index 36e421d7a50e1..6cafa4c4cd3ce 100644 --- a/crates/anvil/src/eth/pool/transactions.rs +++ b/crates/anvil/src/eth/pool/transactions.rs @@ -98,6 +98,11 @@ impl PoolTransaction { pub fn gas_price(&self) -> u128 { self.pending_transaction.transaction.gas_price() } + + /// Returns the type of the transaction + pub fn tx_type(&self) -> u8 { + self.pending_transaction.transaction.r#type().unwrap_or_default() + } } impl fmt::Debug for PoolTransaction { diff --git a/crates/anvil/src/eth/util.rs b/crates/anvil/src/eth/util.rs index ca66f2ed3d3c5..beb73276c3b4d 100644 --- a/crates/anvil/src/eth/util.rs +++ b/crates/anvil/src/eth/util.rs @@ -1,7 +1,7 @@ use alloy_primitives::Address; -use foundry_evm::revm::{ +use revm::{ precompile::{PrecompileSpecId, Precompiles}, - primitives::SpecId, + primitives::hardfork::SpecId, }; use std::fmt; diff --git a/crates/anvil/src/evm.rs b/crates/anvil/src/evm.rs index eef0800eae119..53ace61eaf858 100644 --- a/crates/anvil/src/evm.rs +++ b/crates/anvil/src/evm.rs @@ -1,81 +1,84 @@ +use std::fmt::Debug; + use alloy_primitives::Address; -use foundry_evm::revm::precompile::Precompile; -use std::{fmt::Debug, sync::Arc}; +use revm::precompile::Precompiles; /// Object-safe trait that enables injecting extra precompiles when using /// `anvil` as a library. pub trait PrecompileFactory: Send + Sync + Unpin + Debug { /// Returns a set of precompiles to extend the EVM with. - fn precompiles(&self) -> Vec<(Address, Precompile)>; + fn precompiles(&self) -> Vec<(Address, Precompiles)>; } -/// Appends a handler register to `evm` that injects the given `precompiles`. -/// -/// This will add an additional handler that extends the default precompiles with the given set of -/// precompiles. -pub fn inject_precompiles( - evm: &mut revm::Evm<'_, I, DB>, - precompiles: Vec<(Address, Precompile)>, -) { - evm.handler.append_handler_register_box(Box::new(move |handler| { - let precompiles = precompiles.clone(); - let prev = handler.pre_execution.load_precompiles.clone(); - handler.pre_execution.load_precompiles = Arc::new(move || { - let mut cx = prev(); - cx.extend(precompiles.iter().cloned().map(|(a, b)| (a, b.into()))); - cx - }); - })); -} +// /// Appends a handler register to `evm` that injects the given `precompiles`. +// /// +// /// This will add an additional handler that extends the default precompiles with the given set +// of /// precompiles. +// pub fn inject_precompiles( +// evm: &mut revm::Evm<'_, I, DB>, +// precompiles: Precompiles, +// ) { +// evm.handler.append_handler_register_box(Box::new(move |handler| { +// let precompiles = precompiles.clone(); +// let prev = handler.pre_execution.load_precompiles.clone(); +// handler.pre_execution.load_precompiles = Arc::new(move || { +// let mut cx = prev(); +// cx.extend(precompiles.iter().cloned().map(|(a, b)| (a, b.into()))); +// cx +// }); +// })); +// } -#[cfg(test)] -mod tests { - use crate::{evm::inject_precompiles, PrecompileFactory}; - use alloy_primitives::Address; - use foundry_evm::revm::primitives::{address, Bytes, Precompile, PrecompileResult, SpecId}; - use revm::primitives::PrecompileOutput; +// #[cfg(test)] +// mod tests { +// use crate::{evm::inject_precompiles, PrecompileFactory}; +// use alloy_primitives::{address, Address, Bytes}; +// use revm::{ +// precompile::{PrecompileOutput, PrecompileResult, Precompiles}, +// primitives::hardfork::SpecId, +// }; - #[test] - fn build_evm_with_extra_precompiles() { - const PRECOMPILE_ADDR: Address = address!("0x0000000000000000000000000000000000000071"); +// #[test] +// fn build_evm_with_extra_precompiles() { +// const PRECOMPILE_ADDR: Address = address!("0x0000000000000000000000000000000000000071"); - fn my_precompile(_bytes: &Bytes, _gas_limit: u64) -> PrecompileResult { - Ok(PrecompileOutput { bytes: Bytes::new(), gas_used: 0 }) - } +// fn my_precompile(_bytes: &Bytes, _gas_limit: u64) -> PrecompileResult { +// Ok(PrecompileOutput { bytes: Bytes::new(), gas_used: 0 }) +// } - #[derive(Debug)] - struct CustomPrecompileFactory; +// #[derive(Debug)] +// struct CustomPrecompileFactory; - impl PrecompileFactory for CustomPrecompileFactory { - fn precompiles(&self) -> Vec<(Address, Precompile)> { - vec![(PRECOMPILE_ADDR, Precompile::Standard(my_precompile))] - } - } +// impl PrecompileFactory for CustomPrecompileFactory { +// fn precompiles(&self) -> Vec<(Address, Precompile)> { +// vec![(PRECOMPILE_ADDR, Precompile::Standard(my_precompile))] +// } +// } - let db = revm::db::EmptyDB::default(); - let env = Box::::default(); - let spec = SpecId::LATEST; - let handler_cfg = revm::primitives::HandlerCfg::new(spec); - let inspector = revm::inspectors::NoOpInspector; - let context = revm::Context::new(revm::EvmContext::new_with_env(db, env), inspector); - let handler = revm::Handler::new(handler_cfg); - let mut evm = revm::Evm::new(context, handler); - assert!(!evm - .handler - .pre_execution() - .load_precompiles() - .addresses() - .any(|&addr| addr == PRECOMPILE_ADDR)); +// let db = revm::db::EmptyDB::default(); +// let env = Box::::default(); +// let spec = SpecId::default(); +// let handler_cfg = revm::primitives::HandlerCfg::new(spec); +// let inspector = revm::inspectors::NoOpInspector; +// let context = revm::Context::new(revm::EvmContext::new_with_env(db, env), inspector); +// let handler = revm::Handler::new(handler_cfg); +// let mut evm = revm::Evm::new(context, handler); +// assert!(!evm +// .handler +// .pre_execution() +// .load_precompiles() +// .addresses() +// .any(|&addr| addr == PRECOMPILE_ADDR)); - inject_precompiles(&mut evm, CustomPrecompileFactory.precompiles()); - assert!(evm - .handler - .pre_execution() - .load_precompiles() - .addresses() - .any(|&addr| addr == PRECOMPILE_ADDR)); +// inject_precompiles(&mut evm, CustomPrecompileFactory.precompiles()); +// assert!(evm +// .handler +// .pre_execution() +// .load_precompiles() +// .addresses() +// .any(|&addr| addr == PRECOMPILE_ADDR)); - let result = evm.transact().unwrap(); - assert!(result.result.is_success()); - } -} +// let result = evm.transact().unwrap(); +// assert!(result.result.is_success()); +// } +// } diff --git a/crates/anvil/src/hardfork.rs b/crates/anvil/src/hardfork.rs index d85e12f7decfa..53ddd4c6740df 100644 --- a/crates/anvil/src/hardfork.rs +++ b/crates/anvil/src/hardfork.rs @@ -1,7 +1,9 @@ +use std::str::FromStr; + use alloy_rpc_types::BlockNumberOrTag; use eyre::bail; -use foundry_evm::revm::primitives::SpecId; -use std::str::FromStr; +use op_revm::OpSpecId; +use revm::primitives::hardfork::SpecId; #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum ChainHardfork { @@ -25,7 +27,7 @@ impl From for SpecId { fn from(fork: ChainHardfork) -> Self { match fork { ChainHardfork::Ethereum(hardfork) => hardfork.into(), - ChainHardfork::Optimism(hardfork) => hardfork.into(), + ChainHardfork::Optimism(hardfork) => hardfork.into_eth_spec(), } } } @@ -178,9 +180,15 @@ pub enum OptimismHardfork { Fjord, Granite, Holocene, - Isthmus, #[default] - Latest, + Isthmus, +} + +impl OptimismHardfork { + pub fn into_eth_spec(self) -> SpecId { + let op_spec: OpSpecId = self.into(); + op_spec.into_eth_spec() + } } impl FromStr for OptimismHardfork { @@ -197,14 +205,13 @@ impl FromStr for OptimismHardfork { "granite" => Self::Granite, "holocene" => Self::Holocene, "isthmus" => Self::Isthmus, - "latest" => Self::Latest, _ => bail!("Unknown hardfork {s}"), }; Ok(hardfork) } } -impl From for SpecId { +impl From for OpSpecId { fn from(fork: OptimismHardfork) -> Self { match fork { OptimismHardfork::Bedrock => Self::BEDROCK, @@ -215,7 +222,6 @@ impl From for SpecId { OptimismHardfork::Granite => Self::GRANITE, OptimismHardfork::Holocene => Self::HOLOCENE, OptimismHardfork::Isthmus => Self::ISTHMUS, - OptimismHardfork::Latest => Self::LATEST, } } } diff --git a/crates/anvil/src/lib.rs b/crates/anvil/src/lib.rs index d5576596e1ea0..b48ad1197569a 100644 --- a/crates/anvil/src/lib.rs +++ b/crates/anvil/src/lib.rs @@ -23,7 +23,6 @@ use alloy_signer_local::PrivateKeySigner; use eth::backend::fork::ClientFork; use eyre::Result; use foundry_common::provider::{ProviderBuilder, RetryProvider}; -use foundry_evm::revm; use futures::{FutureExt, TryFutureExt}; use parking_lot::Mutex; use server::try_spawn_ipc; @@ -48,13 +47,15 @@ pub use config::{ }; mod hardfork; -pub use hardfork::EthereumHardfork; +pub use hardfork::{EthereumHardfork, OptimismHardfork}; /// ethereum related implementations pub mod eth; /// Evm related abstractions mod evm; -pub use evm::{inject_precompiles, PrecompileFactory}; +// pub use evm::{inject_precompiles, PrecompileFactory}; +pub use evm::PrecompileFactory; + /// support for polling filters pub mod filter; /// commandline output diff --git a/crates/anvil/test-data/state-dump-legacy-stress.json b/crates/anvil/test-data/state-dump-legacy-stress.json index f6605d5add4e3..b7a18c94cad40 100644 --- a/crates/anvil/test-data/state-dump-legacy-stress.json +++ b/crates/anvil/test-data/state-dump-legacy-stress.json @@ -1 +1 @@ -{"block":{"number":"0x5","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66b200cb","gas_limit":"0x1c9c380","basefee":"0x12e09c7a","difficulty":"0x0","prevrandao":"0xe7ef87fc7c2090741a6749a087e4ca8092cb4d07136008799e4ebeac3b69e34a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0x1088aa62285a00","code":"0x","storage":{}},"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd":{"nonce":1,"balance":"0x0","code":"0x6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x19ba1fac55eea44d12a01372a8eb0c2ebbf9ca21":{"nonce":1,"balance":"0x21e19df7c2963f0ac6b","code":"0x","storage":{}},"0x19c6ab860dbe2bc433574193a4409770a8748bf6":{"nonce":1,"balance":"0x21e19df8da6b7bdc410","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x40567ec443c1d1872af5155755ac3803cc3fe61e":{"nonce":1,"balance":"0x21e19da82562f921b40","code":"0x","storage":{}},"0x47d08dad17ccb558b3ea74b1a0e73a9cc804a9dc":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","storage":{"0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0x0"}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":2,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x8138ef7cf908021d117e542120b7a39065016107":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","storage":{}},"0x83a0444b93927c3afcbe46e522280390f748e171":{"nonce":1,"balance":"0x0","code":"0x6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c63430008110033","storage":{"0x5a648c35a2f5512218b4683cf10e03f5b7c9dc7346e1bf77d304ae97f60f592b":"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xc67e2bd3108604cf0168c0e5ef9cd6d78b9bb14b":{"nonce":1,"balance":"0x21e19c6edb7e2445f20","code":"0x","storage":{}},"0xeb045d78d273107348b0300c01d29b7552d622ab":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e08b86820a43ea","code":"0x","storage":{}}},"best_block_number":"0x5","blocks":[{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xcd346446ed010523161f40a5f2b512def549bfb79e165b4354488738416481f2","transactionsRoot":"0xb3a4689832e0b599260ae70362ffcf224b60571b35ff8836904a3d81e2675d66","receiptsRoot":"0x2d13fdc120ab90536fed583939de7fb68b64926a306c1f629593ca9c2c93b198","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x3ea90d","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x2e0b6260","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3ea90d","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b5061494f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xbc73db80bf4b8784ba10a8910a0b7ef85f6846d102b41dd990969ea205335354"}}],"ommers":[]},{"header":{"parentHash":"0x026ae0c6ae91f186a9befa1ac8be30eea35e30e77de51a731085221e5cd39209","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x6e4969a136061ca7a390d12830d47a151585325a8d396819fb2b958ff85e9f8f","receiptsRoot":"0xc3e81df67d3e2a6c8345a954ef250cfcc41abcc2292a5aa263071124533fc9ad","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x3c0f6","timestamp":"0x66b200ce","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x18993a68","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3c0f6","maxFeePerGas":"0x5d4285cd","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b50610380806100206000396000f3fe6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x2476e039803622aeb040f924f04c493f559aed3d6c9372ab405cb33c8c695328"}}],"ommers":[]},{"header":{"parentHash":"0x3d22100ac0ee8d5cde334f7f926191a861b0648971ebc179547df28a0224c6d0","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9511d4711e5c30a72b0bff38a261daa75dcc5ba8b772d970a5c742244b4c861b","transactionsRoot":"0xba5fff578d3d6c2cd63acbe9bca353eaa6fe22a5c408956eff49106e0a96c507","receiptsRoot":"0xbae111f01cb07677e3a8c5031546138407c01bc964d3493d732dc4edf47d36d3","logsBloom":"0x00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000001000000000000000000000400000001000010000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x5","gasLimit":"0x1c9c380","gasUsed":"0xcae7","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x12e09c7a","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xcc4d","maxFeePerGas":"0x557e5ec4","maxPriorityFeePerGas":"0x3b9aca00","to":"0x83a0444b93927c3afcbe46e522280390f748e171","value":"0x0","accessList":[],"input":"0x3659cfe6000000000000000000000000108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xf88e7b19ee347145c257e0cf7ac4ecc2bae83ca79d7edaa231e71d3213aeb151"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9c8eaf493f8b4edce2ba1647343eadcc0989cf461e712c0a6253ff2ca1842bb7","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xdd07c07470e1deff3749831f0f1ad8d4b6e35505e83b3c6ea14181716197cd8a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x24a1ab52","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200c9","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xf6930be4847cac5017bbcbec2756eed19f36b4196526a98a88e311c296e3a9be","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cc","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x200d75e8","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x4","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1592fbf9","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x149d41e3b89d8324cef3feff98ef308e97bafe8745cc8461c60172bc7d4c44ba","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x0b44110186e52ff0ceb6b0776ca2992c94144a4ed712eef65ea038260ef0fcc7","receiptsRoot":"0xc2823b8eb4730d9f2657137cc2ddc2c4f22ab68e0ab826236cf6a1551ca2b3a5","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0xe61f9","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342770c0","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xe94d1","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060008061002661006d60201b61081b1760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610141565b60008060405160200161007f90610121565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b600061010b60238361009e565b9150610116826100af565b604082019050919050565b6000602082019050818103600083015261013a816100fe565b9050919050565b611000806101506000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x4feae6769d748b4f0f7c9bf21d782236c88f13906789a3ec602961296e4c3e43"}}],"ommers":[]},{"header":{"parentHash":"0xb3535af5103fd1c2bbd6dc7ff23f0799037a6542c231ebcb85abd776560fa512","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x23d74fb99ff6e42cbb5c33f92b078e37be6af2b6092459b103ff7059a6517ebc","transactionsRoot":"0x9eab45eca206fe11c107ea985c7d02fcfa442836aea3e04ba11dc4df587d5aa6","receiptsRoot":"0xe25abcfa973db8c55f73292137c626430de130a382ad4466337fefb0f7c8fde0","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x3ce3f","timestamp":"0x66b200cd","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1c0bc72b","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3d8a8","maxFeePerGas":"0x6211577c","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060405161068538038061068583398181016040528101906100329190610275565b818181600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361009b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100ae8161019d60201b61004f1760201c565b6100ef57806040517f8a8b41ec0000000000000000000000000000000000000000000000000000000081526004016100e691906102c4565b60405180910390fd5b806100fe6101b060201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050806101536101e160201b6100621760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050610414565b600080823b905060008111915050919050565b6000806040516020016101c290610362565b6040516020818303038152906040528051906020012090508091505090565b6000806040516020016101f3906103f4565b6040516020818303038152906040528051906020012090508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061024282610217565b9050919050565b61025281610237565b811461025d57600080fd5b50565b60008151905061026f81610249565b92915050565b6000806040838503121561028c5761028b610212565b5b600061029a85828601610260565b92505060206102ab85828601610260565b9150509250929050565b6102be81610237565b82525050565b60006020820190506102d960008301846102b5565b92915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b600061034c6021836102df565b9150610357826102f0565b604082019050919050565b6000602082019050818103600083015261037b8161033f565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006103de6023836102df565b91506103e982610382565b604082019050919050565b6000602082019050818103600083015261040d816103d1565b9050919050565b610262806104236000396000f3fe6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c6343000811003300000000000000000000000047d08dad17ccb558b3ea74b1a0e73a9cc804a9dc000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xb6794d5c7abed6f91d447e8efb72ef2580595a6d7c8dee57ba1dbb330970146a"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x29dd5614","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]}]} \ No newline at end of file +{"block":{"number":5,"beneficiary":"0x0000000000000000000000000000000000000000","timestamp":1722941643,"gas_limit":30000000,"basefee":316710010,"difficulty":"0x0","prevrandao":"0xe7ef87fc7c2090741a6749a087e4ca8092cb4d07136008799e4ebeac3b69e34a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0x1088aa62285a00","code":"0x","storage":{}},"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd":{"nonce":1,"balance":"0x0","code":"0x6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x19ba1fac55eea44d12a01372a8eb0c2ebbf9ca21":{"nonce":1,"balance":"0x21e19df7c2963f0ac6b","code":"0x","storage":{}},"0x19c6ab860dbe2bc433574193a4409770a8748bf6":{"nonce":1,"balance":"0x21e19df8da6b7bdc410","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x40567ec443c1d1872af5155755ac3803cc3fe61e":{"nonce":1,"balance":"0x21e19da82562f921b40","code":"0x","storage":{}},"0x47d08dad17ccb558b3ea74b1a0e73a9cc804a9dc":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","storage":{"0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0x0"}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":2,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x8138ef7cf908021d117e542120b7a39065016107":{"nonce":1,"balance":"0x0","code":"0x608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","storage":{}},"0x83a0444b93927c3afcbe46e522280390f748e171":{"nonce":1,"balance":"0x0","code":"0x6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c63430008110033","storage":{"0x5a648c35a2f5512218b4683cf10e03f5b7c9dc7346e1bf77d304ae97f60f592b":"0x108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","0x5c7865864a2a990d80b5bb5c40e7b73a029960dc711fbb56120dfab976e92ea3":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xc67e2bd3108604cf0168c0e5ef9cd6d78b9bb14b":{"nonce":1,"balance":"0x21e19c6edb7e2445f20","code":"0x","storage":{}},"0xeb045d78d273107348b0300c01d29b7552d622ab":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e08b86820a43ea","code":"0x","storage":{}}},"best_block_number":5,"blocks":[{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xcd346446ed010523161f40a5f2b512def549bfb79e165b4354488738416481f2","transactionsRoot":"0xb3a4689832e0b599260ae70362ffcf224b60571b35ff8836904a3d81e2675d66","receiptsRoot":"0x2d13fdc120ab90536fed583939de7fb68b64926a306c1f629593ca9c2c93b198","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x3ea90d","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x2e0b6260","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3ea90d","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b5061494f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632a952b2d1461005c57806350c946fe14610085578063625ca21c146100a5578063daa250be146100c6578063deba1b98146100d9575b600080fd5b61006f61006a366004613a63565b6100ec565b60405161007c9190613a7c565b60405180910390f35b610098610093366004613a63565b61011c565b60405161007c9190613b21565b6100b86100b3366004613c92565b610276565b60405190815260200161007c565b61006f6100d4366004613d5f565b6102bb565b6100b86100e7366004613c92565b6102d6565b6100f46139e4565b6040805160008082526020820190815281830190925261011691849190610310565b92915050565b6101416040805160608101909152806000815260200160608152602001606081525090565b61014a82610ab6565b60408051606081019091528154909190829060ff16600981111561017057610170613aa7565b600981111561018157610181613aa7565b815260200160018201805461019590613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546101c190613dc2565b801561020e5780601f106101e35761010080835404028352916020019161020e565b820191906000526020600020905b8154815290600101906020018083116101f157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561026657602002820191906000526020600020905b815481526020019060010190808311610252575b5050505050815250509050919050565b600080604051806060016040528086600981111561029657610296613aa7565b81526020018581526020018481525090506102b081610ac1565b9150505b9392505050565b6102c36139e4565b6102ce848484610310565b949350505050565b60008060405180606001604052808660098111156102f6576102f6613aa7565b81526020018581526020018481525090506102b081610acc565b6103186139e4565b81518351146103a05760408051634bab873760e11b81526004810191909152600d60448201526c72756e74696d6556616c75657360981b606482015260806024820152602260848201527f6d7573742062652073616d65206c656e6774682061732072756e74696d654b6560a482015261797360f01b60c482015260e4015b60405180910390fd5b60006103ab85610c26565b805490915060ff1660018160098111156103c7576103c7613aa7565b036104755761046c6103da838787610c84565b8360010180546103e990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461041590613dc2565b80156104625780601f1061043757610100808354040283529160200191610462565b820191906000526020600020905b81548152906001019060200180831161044557829003601f168201915b5050505050610d46565b925050506102b4565b600281600981111561048957610489613aa7565b036105305761046c61049c838787610c84565b8360010180546104ab90613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546104d790613dc2565b80156105245780601f106104f957610100808354040283529160200191610524565b820191906000526020600020905b81548152906001019060200180831161050757829003601f168201915b50505050508787610ebb565b600381600981111561054457610544613aa7565b036105de5761046c82600101805461055b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461058790613dc2565b80156105d45780601f106105a9576101008083540402835291602001916105d4565b820191906000526020600020905b8154815290600101906020018083116105b757829003601f168201915b5050505050610f59565b60048160098111156105f2576105f2613aa7565b0361068c5761046c82600101805461060990613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461063590613dc2565b80156106825780601f1061065757610100808354040283529160200191610682565b820191906000526020600020905b81548152906001019060200180831161066557829003601f168201915b5050505050611087565b60058160098111156106a0576106a0613aa7565b0361073a5761046c8260010180546106b790613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546106e390613dc2565b80156107305780601f1061070557610100808354040283529160200191610730565b820191906000526020600020905b81548152906001019060200180831161071357829003601f168201915b505050505061131e565b600981600981111561074e5761074e613aa7565b036107ea5761046c82600101805461076590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461079190613dc2565b80156107de5780601f106107b3576101008083540402835291602001916107de565b820191906000526020600020905b8154815290600101906020018083116107c157829003601f168201915b505050505086866114b5565b60068160098111156107fe576107fe613aa7565b036108a35761046c610811838787610c84565b83600101805461082090613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461084c90613dc2565b80156108995780601f1061086e57610100808354040283529160200191610899565b820191906000526020600020905b81548152906001019060200180831161087c57829003601f168201915b50505050506115c7565b60078160098111156108b7576108b7613aa7565b036109ec576040805160608101909152825461046c91908490829060ff1660098111156108e6576108e6613aa7565b60098111156108f7576108f7613aa7565b815260200160018201805461090b90613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461093790613dc2565b80156109845780601f1061095957610100808354040283529160200191610984565b820191906000526020600020905b81548152906001019060200180831161096757829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156109dc57602002820191906000526020600020905b8154815260200190600101908083116109c8575b5050505050815250508686611728565b6008816009811115610a0057610a00613aa7565b03610a9a5761046c826001018054610a1790613dc2565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4390613dc2565b8015610a905780601f10610a6557610100808354040283529160200191610a90565b820191906000526020600020905b815481529060010190602001808311610a7357829003601f168201915b50505050506118a5565b6040516323a9bbc960e01b815260048101879052602401610397565b600061011682610c26565b6000610116826118ea565b6000610ad782610ac1565b9050610ae28161192a565b15610b35577fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e81836000015184602001518560400151604051610b289493929190613e32565b60405180910390a1919050565b610b3e82611a8c565b610b5d578160405163382bbbc960e11b81526004016103979190613b21565b60005b826040015151811015610bd957610b9383604001518281518110610b8657610b86613e6a565b602002602001015161192a565b610bd15782604001518181518110610bad57610bad613e6a565b6020026020010151604051632f19f96160e11b815260040161039791815260200190565b600101610b60565b50610be382611c31565b8351602085015160408087015190519395507fcb64985827770858ec421ad26da7e558c757541643036ce44d6b4eb9e8e5dc5e9450610b28938693929190613e32565b604080516020808201839052606082018190527f696f2e73796e7468657469782e6f7261636c652d6d616e616765722e4e6f6465608080840191909152828401949094528251808303909401845260a0909101909152815191012090565b600283015460609067ffffffffffffffff811115610ca457610ca4613b9a565b604051908082528060200260200182016040528015610cdd57816020015b610cca6139e4565b815260200190600190039081610cc25790505b50905060005b6002850154811015610d3e57610d19856002018281548110610d0757610d07613e6a565b90600052602060002001548585610310565b828281518110610d2b57610d2b613e6a565b6020908102919091010152600101610ce3565b509392505050565b610d4e6139e4565b600082806020019051810190610d649190613e80565b90506000816008811115610d7a57610d7a613aa7565b03610d9057610d8884611ca5565b915050610116565b6001816008811115610da457610da4613aa7565b03610db257610d8884611d0d565b6002816008811115610dc657610dc6613aa7565b03610dd457610d8884611d90565b6003816008811115610de857610de8613aa7565b03610df657610d8884611e13565b6004816008811115610e0a57610e0a613aa7565b03610e1857610d8884611ec9565b6005816008811115610e2c57610e2c613aa7565b03610e3a57610d8884612009565b6006816008811115610e4e57610e4e613aa7565b03610e5c57610d88846120e4565b6007816008811115610e7057610e70613aa7565b03610e7e57610d888461220c565b6008816008811115610e9257610e92613aa7565b03610ea057610d88846122ce565b80604051631be413d360e11b81526004016103979190613ea1565b610ec36139e4565b600084806020019051810190610ed99190613ed3565b604051631ecba7c360e31b81529091506001600160a01b0382169063f65d3e1890610f0e908990899089908990600401613ef0565b608060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190613f91565b9695505050505050565b610f616139e4565b600080600084806020019051810190610f7a9190613fe8565b92509250925060008390506000806000836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015610fc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fec9190614041565b509350509250925060008660001461100f5761100a8585858a6123c7565b611011565b825b905060128660ff161161103b5761103661102f60ff881660126140a7565b82906124c2565b611053565b61105361104c601260ff89166140a7565b82906124dc565b9050604051806080016040528082815260200183815260200160008152602001600081525098505050505050505050919050565b61108f6139e4565b600080600080600080878060200190518101906110ac91906140ba565b604080516002808252606082018352979d50959b50939950919750955093506000929060208301908036833701905050905081816000815181106110f2576110f2613e6a565b602002602001019063ffffffff16908163ffffffff168152505060008160018151811061112157611121613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526000906001600160a01b0385169063883bdbfd90611165908590600401614143565b600060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111aa91908101906141f5565b5090506000816000815181106111c2576111c2613e6a565b6020026020010151826001815181106111dd576111dd613e6a565b60200260200101516111ef91906142c1565b9050600061121761120563ffffffff87166124f6565b61120f9084614304565b60060b61252d565b905060008260060b12801561124c575061123b63ffffffff8616612569565b612569565b8260060b6112499190614342565b15155b1561125f578061125b81614356565b9150505b600061126d6012600a61445d565b9050600061128061123684848f8f612593565b905060006112908a60ff16612569565b61129c8c60ff16612569565b6112a6919061446c565b905060008082136112d1576112cc6112c56112c084614493565b612686565b84906124dc565b6112e4565b6112e46112dd83612686565b84906124c2565b905060405180608001604052808281526020014281526020016000815260200160008152509e505050505050505050505050505050919050565b6113266139e4565b60008060008480602001905181019061133f91906144bf565b91945092509050826000826113bc576040516396834ad360e01b8152600481018590526001600160a01b038316906396834ad390602401608060405180830381865afa158015611393573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b791906144f5565b611425565b604051639474f45b60e01b8152600481018590526001600160a01b03831690639474f45b90602401608060405180830381865afa158015611401573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142591906144f5565b90506000816040015160030b601261143d919061456f565b90506000808213611467576114626114576112c084614493565b845160070b906124dc565b61147e565b61147e61147383612686565b845160070b906124c2565b9050604051806080016040528082815260200184606001518152602001600081526020016000815250975050505050505050919050565b6114bd6139e4565b6000806000868060200190518101906114d69190614597565b92509250925060005b8651811015611545578681815181106114fa576114fa613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b0361153d5785818151811061152f5761152f613e6a565b602002602001015160001c91505b6001016114df565b5060408051600180825281830190925260009160208083019080368337019050509050828160008151811061157c5761157c613e6a565b602002602001018181525050836001838360405160200161159f939291906145ce565b60408051601f198184030181529082905263cf2cabdf60e01b82526103979291600401614603565b6115cf6139e4565b6000828060200190518101906115e59190614627565b90506000846000815181106115fc576115fc613e6a565b602002602001015160000151905060008560018151811061161f5761161f613e6a565b6020026020010151600001519050808214611702576000611653601261164d611648858761446c565b6126a9565b906124c2565b905082158061167b5750611666836126a9565b6116709082614640565b61167985612569565b125b15611700576002875111156116b0578660028151811061169d5761169d613e6a565b6020026020010151945050505050610116565b826000036116d15760405163014cc07160e01b815260040160405180910390fd5b6116da836126a9565b6116e49082614640565b60405163dcac091960e01b815260040161039791815260200190565b505b8560008151811061171557611715613e6a565b6020026020010151935050505092915050565b6117306139e4565b6000846020015180602001905181019061174a9190614627565b905060005b84518110156117bc5784818151811061176a5761176a613e6a565b6020026020010151717374616c656e657373546f6c6572616e636560701b036117b4576117ad8482815181106117a2576117a2613e6a565b602002602001015190565b91506117bc565b60010161174f565b50600085604001516000815181106117d6576117d6613e6a565b6020026020010151905060006117ed828787610310565b60208101519091506117ff84426140a7565b1161180e5792506102b4915050565b86604001515160010361187157866040015160008151811061183257611832613e6a565b602002602001015181600001518260200151604051631808066560e21b8152600401610397939291909283526020830191909152604082015260600190565b61189a876040015160018151811061188b5761188b613e6a565b60200260200101518787610310565b979650505050505050565b6118ad6139e4565b6040518060800160405280838060200190518101906118cc9190614627565b81526020014281526020016000815260200160008152509050919050565b600081600001518260200151836040015160405160200161190d9392919061466e565b604051602081830303815290604052805190602001209050919050565b60008061193683610c26565b60408051606081019091528154909190829060ff16600981111561195c5761195c613aa7565b600981111561196d5761196d613aa7565b815260200160018201805461198190613dc2565b80601f01602080910402602001604051908101604052809291908181526020018280546119ad90613dc2565b80156119fa5780601f106119cf576101008083540402835291602001916119fa565b820191906000526020600020905b8154815290600101906020018083116119dd57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015611a5257602002820191906000526020600020905b815481526020019060010190808311611a3e575b505050505081525050905060006009811115611a7057611a70613aa7565b81516009811115611a8357611a83613aa7565b14159392505050565b6000600182516009811115611aa357611aa3613aa7565b1480611ac15750600682516009811115611abf57611abf613aa7565b145b80611ade5750600782516009811115611adc57611adc613aa7565b145b15611aee57611aec826126c1565b505b600182516009811115611b0357611b03613aa7565b03611b11576101168261284a565b600282516009811115611b2657611b26613aa7565b03611b3457610116826128a5565b600382516009811115611b4957611b49613aa7565b03611b575761011682612973565b600482516009811115611b6c57611b6c613aa7565b03611b7a5761011682612aae565b600582516009811115611b8f57611b8f613aa7565b03611b9d5761011682612e92565b600982516009811115611bb257611bb2613aa7565b03611bc05761011682612fcb565b600682516009811115611bd557611bd5613aa7565b03611be3576101168261300e565b600782516009811115611bf857611bf8613aa7565b03611c065761011682613052565b600882516009811115611c1b57611c1b613aa7565b03611c295761011682613078565b506000919050565b600080611c3d836118ea565b9050611c4881610c26565b8351815491935090839060ff19166001836009811115611c6a57611c6a613aa7565b021790555060208301516001830190611c8390826146ed565b5060408301518051611c9f916002850191602090910190613a0c565b50915091565b611cad6139e4565b60005b8251811015611d07578160200151838281518110611cd057611cd0613e6a565b6020026020010151602001511115611cff57828181518110611cf457611cf4613e6a565b602002602001015191505b600101611cb0565b50919050565b611d156139e4565b81600081518110611d2857611d28613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611d5957611d59613e6a565b6020026020010151600001511215611d8857828181518110611d7d57611d7d613e6a565b602002602001015191505b600101611d39565b611d986139e4565b81600081518110611dab57611dab613e6a565b602002602001015190506000600190505b8251811015611d07578160000151838281518110611ddc57611ddc613e6a565b6020026020010151600001511315611e0b57828181518110611e0057611e00613e6a565b602002602001015191505b600101611dbc565b611e1b6139e4565b60005b8251811015611e9557828181518110611e3957611e39613e6a565b60200260200101516000015182600001818151611e56919061456f565b9052508251839082908110611e6d57611e6d613e6a565b60200260200101516020015182602001818151611e8a91906147ad565b905250600101611e1e565b50611ea08251612569565b8151611eac9190614640565b815281516020820151611ebf91906147c0565b6020820152919050565b611ed16139e4565b611eed826000611ee86001865161123691906140a7565b6130a4565b60028251611efb91906147d4565b600003611fd65760408051600280825260608201909252600091816020015b611f226139e4565b815260200190600190039081611f1a57905050905082600160028551611f4891906147c0565b611f5291906140a7565b81518110611f6257611f62613e6a565b602002602001015181600081518110611f7d57611f7d613e6a565b60200260200101819052508260028451611f9791906147c0565b81518110611fa757611fa7613e6a565b602002602001015181600181518110611fc257611fc2613e6a565b60200260200101819052506102b481611e13565b8160028351611fe591906147c0565b81518110611ff557611ff5613e6a565b60200260200101519050919050565b919050565b6120116139e4565b8160008151811061202457612024613e6a565b60209081029190910101515181528151829060009061204557612045613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061207657612076613e6a565b6020026020010151600001518260000181815161209391906147e8565b90525082518390829081106120aa576120aa613e6a565b602002602001015160200151826020018181516120c791906147ad565b90525060010161205b565b5081518160200151611ebf91906147c0565b6120ec6139e4565b816000815181106120ff576120ff613e6a565b60209081029190910101515181528151829060009061212057612120613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061215157612151613e6a565b60200260200101516000015160000361219e5782818151811061217657612176613e6a565b6020026020010151600001516040516338ee04a760e01b815260040161039791815260200190565b8281815181106121b0576121b0613e6a565b602002602001015160000151826000018181516121cd9190614640565b90525082518390829081106121e4576121e4613e6a565b6020026020010151602001518260200181815161220191906147ad565b905250600101612136565b6122146139e4565b8160008151811061222757612227613e6a565b60209081029190910101515181528151829060009061224857612248613e6a565b6020908102919091018101518101519082015260015b82518110156120d25761229083828151811061227c5761227c613e6a565b602090810291909101015151835190613264565b825282518390829081106122a6576122a6613e6a565b602002602001015160200151826020018181516122c391906147ad565b90525060010161225e565b6122d66139e4565b816000815181106122e9576122e9613e6a565b60209081029190910101515181528151829060009061230a5761230a613e6a565b6020908102919091018101518101519082015260015b82518110156120d25782818151811061233b5761233b613e6a565b6020026020010151600001516000036123605782818151811061217657612176613e6a565b61238983828151811061237557612375613e6a565b602090810291909101015151835190613283565b8252825183908290811061239f5761239f613e6a565b602002602001015160200151826020018181516123bc91906147ad565b905250600101612320565b6000826001826123d785426140a7565b90505b69ffffffffffffffffffff8716156124a3576001600160a01b038816639a6fc8f561240489614818565b6040516001600160e01b031960e084901b16815269ffffffffffffffffffff8216600482015290995060240160a060405180830381865afa925050508015612469575060408051601f3d908101601f1916820190925261246691810190614041565b60015b156124a357858210156124805750505050506124a3565b61248a848961456f565b97508661249681614834565b97505050505050506123da565b6124ac82612569565b6124b69084614640565b98975050505050505050565b60006124d261123683600a61484d565b6102b490846147e8565b60006124ec61123683600a61484d565b6102b49084614640565b6000667fffffffffffff66ffffffffffffff83161115612529576040516329d2678160e21b815260040160405180910390fd5b5090565b6000627fffff19600683900b128061254b5750627fffff600683900b135b1561252957604051630d962f7960e21b815260040160405180910390fd5b60006001600160ff1b038211156125295760405163677c430560e11b815260040160405180910390fd5b60008061259f86613298565b90506fffffffffffffffffffffffffffffffff6001600160a01b0382161161261c5760006125d66001600160a01b03831680614859565b9050836001600160a01b0316856001600160a01b03161061260557612600600160c01b87836136cd565b612614565b6126148187600160c01b6136cd565b92505061267d565b600061263b6001600160a01b03831680680100000000000000006136cd565b9050836001600160a01b0316856001600160a01b03161061266a57612665600160801b87836136cd565b612679565b6126798187600160801b6136cd565b9250505b50949350505050565b6000808212156125295760405163029f024d60e31b815260040160405180910390fd5b600080821215612529576126bc82614493565b610116565b6000805b8260400151518110156128415760006126fa846040015183815181106126ed576126ed613e6a565b6020026020010151610ab6565b60408051606081019091528154909190829060ff16600981111561272057612720613aa7565b600981111561273157612731613aa7565b815260200160018201805461274590613dc2565b80601f016020809104026020016040519081016040528092919081815260200182805461277190613dc2565b80156127be5780601f10612793576101008083540402835291602001916127be565b820191906000526020600020905b8154815290600101906020018083116127a157829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561281657602002820191906000526020600020905b815481526020019060010190808311612802575b505050505081525050905061282a81611a8c565b612838575060009392505050565b506001016126c5565b50600192915050565b60006002826040015151101561286257506000919050565b81602001515160201461287757506000919050565b600082602001518060200190518101906128919190614627565b905060088111156128415750600092915050565b6000602082602001515110156128bd57506000919050565b600082602001518060200190518101906128d79190613ed3565b90506128ea816306e7ea3960e21b6138e2565b6128f75750600092915050565b604051633b70a5bf60e21b81526001600160a01b0382169063edc296fc90612923908690600401613b21565b6020604051808303816000875af1158015612942573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129669190614870565b6128415750600092915050565b6040810151516000901561298957506000919050565b81602001515160601461299e57506000919050565b60008083602001518060200190518101906129b99190613fe8565b92505091506000829050806001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612a01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a259190614041565b5050505050806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c919061488b565b60ff168260ff1614612aa357506000949350505050565b506001949350505050565b60408101515160009015612ac457506000919050565b81602001515160c014612ad957506000919050565b6000806000806000808760200151806020019051810190612afa91906140ba565b9550955095509550955095508360ff16866001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6c919061488b565b60ff1614612b8257506000979650505050505050565b8260ff16856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be8919061488b565b60ff1614612bfe57506000979650505050505050565b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c629190613ed3565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cc89190613ed3565b9050876001600160a01b0316826001600160a01b0316148015612cfc5750866001600160a01b0316816001600160a01b0316145b158015612d385750866001600160a01b0316826001600160a01b0316148015612d365750876001600160a01b0316816001600160a01b0316145b155b15612d4d575060009998505050505050505050565b60128660ff161180612d62575060128560ff16115b15612d77575060009998505050505050505050565b8263ffffffff16600003612d95575060009998505050505050505050565b6040805160028082526060820183526000926020830190803683370190505090508381600081518110612dca57612dca613e6a565b602002602001019063ffffffff16908163ffffffff1681525050600081600181518110612df957612df9613e6a565b63ffffffff9092166020928302919091019091015260405163883bdbfd60e01b81526001600160a01b0386169063883bdbfd90612e3a908490600401614143565b600060405180830381865afa158015612e57573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612e7f91908101906141f5565b5060019c9b505050505050505050505050565b60408101515160009015612ea857506000919050565b816020015151606014612ebd57506000919050565b60008060008460200151806020019051810190612eda91906144bf565b919450925090508281612f55576040516396834ad360e01b8152600481018490526001600160a01b038216906396834ad390602401608060405180830381865afa158015612f2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5091906144f5565b612fbe565b604051639474f45b60e01b8152600481018490526001600160a01b03821690639474f45b90602401608060405180830381865afa158015612f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fbe91906144f5565b5060019695505050505050565b60408101515160009015612fe157506000919050565b816020015151606014612ff657506000919050565b8160200151806020019051810190612aa39190614597565b60008160400151516002148061302957508160400151516003145b61303557506000919050565b81602001515160201461304a57506000919050565b506001919050565b600081604001515160011480613029575081604001515160021461303557506000919050565b6040810151516000901561308e57506000919050565b6020826020015151101561304a57506000919050565b81818082036130b4575050505050565b6000856130da60026130c6888861446c565b6130d09190614640565b6112c0908861456f565b815181106130ea576130ea613e6a565b60200260200101516000015190505b818313613236575b808661310c85612686565b8151811061311c5761311c613e6a565b60200260200101516000015112156131405782613138816148a6565b935050613101565b8561314a83612686565b8151811061315a5761315a613e6a565b60200260200101516000015181121561317f5781613177816148be565b925050613140565b818313613231578561319083612686565b815181106131a0576131a0613e6a565b6020026020010151866131b285612686565b815181106131c2576131c2613e6a565b6020026020010151876131d486612686565b815181106131e4576131e4613e6a565b60200260200101886131f586612686565b8151811061320557613205613e6a565b602002602001018290528290525050828061321f906148a6565b935050818061322d906148be565b9250505b6130f9565b81851215613249576132498686846130a4565b8383121561325c5761325c8684866130a4565b505050505050565b6000670de0b6b3a764000061327983856147e8565b6102b49190614640565b600081613279670de0b6b3a7640000856147e8565b60008060008360020b126132b8576132b3600284900b612686565b6132c8565b6132c86112c0600285900b614493565b90506132e36112c06132dd620d89e7196148db565b60020b90565b8111156133165760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401610397565b60008160011660000361332d57600160801b61333f565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff169050600282161561337e576080613379826ffff97272373d413259a46990580e213a614859565b901c90505b60048216156133a85760806133a3826ffff2e50f5f656932ef12357cf3c7fdcc614859565b901c90505b60088216156133d25760806133cd826fffe5caca7e10e4e61c3624eaa0941cd0614859565b901c90505b60108216156133fc5760806133f7826fffcb9843d60f6159c9db58835c926644614859565b901c90505b6020821615613426576080613421826fff973b41fa98c081472e6896dfb254c0614859565b901c90505b604082161561345057608061344b826fff2ea16466c96a3843ec78b326b52861614859565b901c90505b608082161561347a576080613475826ffe5dee046a99a2a811c461f1969c3053614859565b901c90505b6101008216156134a55760806134a0826ffcbe86c7900a88aedcffc83b479aa3a4614859565b901c90505b6102008216156134d05760806134cb826ff987a7253ac413176f2b074cf7815e54614859565b901c90505b6104008216156134fb5760806134f6826ff3392b0822b70005940c7a398e4b70f3614859565b901c90505b610800821615613526576080613521826fe7159475a2c29b7443b29c7fa6e889d9614859565b901c90505b61100082161561355157608061354c826fd097f3bdfd2022b8845ad8f792aa5825614859565b901c90505b61200082161561357c576080613577826fa9f746462d870fdf8a65dc1f90e061e5614859565b901c90505b6140008216156135a75760806135a2826f70d869a156d2a1b890bb3df62baf32f7614859565b901c90505b6180008216156135d25760806135cd826f31be135f97d08fd981231505542fcfa6614859565b901c90505b620100008216156135fe5760806135f9826f09aa508b5b7a84e1c677de54f3e99bc9614859565b901c90505b62020000821615613629576080613624826e5d6af8dedb81196699c329225ee604614859565b901c90505b6204000082161561365357608061364e826d2216e584f5fa1ea926041bedfe98614859565b901c90505b6208000082161561367b576080613676826b048a170391f7dc42444e8fa2614859565b901c90505b60008460020b131561369657613693816000196147c0565b90505b6102ce6136a8640100000000836147d4565b156136b45760016136b7565b60005b6136c89060ff16602084901c6147ad565b6139ba565b6000808060001985870985870292508281108382030391505080600003613749576000841161373e5760405162461bcd60e51b815260206004820152601960248201527f48616e646c65206e6f6e2d6f766572666c6f77206361736573000000000000006044820152606401610397565b5082900490506102b4565b8084116137985760405162461bcd60e51b815260206004820152601960248201527f70726576656e74732064656e6f6d696e61746f72203d3d2030000000000000006044820152606401610397565b60008486880980840393811190920391905060006137d06137b887612569565b6137c188612569565b6137ca90614493565b16612686565b9586900495938490049360008190030460010190506137ef8184614859565b909317926000613800876003614859565b600218905061380f8188614859565b61381a9060026140a7565b6138249082614859565b90506138308188614859565b61383b9060026140a7565b6138459082614859565b90506138518188614859565b61385c9060026140a7565b6138669082614859565b90506138728188614859565b61387d9060026140a7565b6138879082614859565b90506138938188614859565b61389e9060026140a7565b6138a89082614859565b90506138b48188614859565b6138bf9060026140a7565b6138c99082614859565b90506138d58186614859565b9998505050505050505050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b1790529051600091829182916001600160a01b0387169161394391906148fd565b6000604051808303816000865af19150503d8060008114613980576040519150601f19603f3d011682016040523d82523d6000602084013e613985565b606091505b50915091508161399a57600092505050610116565b80516000036139ae57600092505050610116565b60200151949350505050565b60006001600160a01b038211156125295760405163dccde8ed60e01b815260040160405180910390fd5b6040518060800160405280600081526020016000815260200160008152602001600081525090565b828054828255906000526020600020908101928215613a47579160200282015b82811115613a47578251825591602001919060010190613a2c565b506125299291505b808211156125295760008155600101613a4f565b600060208284031215613a7557600080fd5b5035919050565b8151815260208083015190820152604080830151908201526060808301519082015260808101610116565b634e487b7160e01b600052602160045260246000fd5b600a8110613acd57613acd613aa7565b9052565b60005b83811015613aec578181015183820152602001613ad4565b50506000910152565b60008151808452613b0d816020860160208601613ad1565b601f01601f19169290920160200192915050565b60006020808352613b358184018551613abd565b8084015160606040850152613b4d6080850182613af5565b6040860151858203601f19016060870152805180835290840192506000918401905b80831015613b8f5783518252928401926001929092019190840190613b6f565b509695505050505050565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613bd357613bd3613b9a565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715613c0257613c02613b9a565b604052919050565b600067ffffffffffffffff821115613c2457613c24613b9a565b5060051b60200190565b600082601f830112613c3f57600080fd5b81356020613c54613c4f83613c0a565b613bd9565b8083825260208201915060208460051b870101935086841115613c7657600080fd5b602086015b84811015613b8f5780358352918301918301613c7b565b600080600060608486031215613ca757600080fd5b8335600a8110613cb657600080fd5b925060208481013567ffffffffffffffff80821115613cd457600080fd5b818701915087601f830112613ce857600080fd5b813581811115613cfa57613cfa613b9a565b613d0c601f8201601f19168501613bd9565b8181528985838601011115613d2057600080fd5b818585018683013760009181019094015291935060408601359180831115613d4757600080fd5b5050613d5586828701613c2e565b9150509250925092565b600080600060608486031215613d7457600080fd5b83359250602084013567ffffffffffffffff80821115613d9357600080fd5b613d9f87838801613c2e565b93506040860135915080821115613db557600080fd5b50613d5586828701613c2e565b600181811c90821680613dd657607f821691505b602082108103611d0757634e487b7160e01b600052602260045260246000fd5b60008151808452602080850194506020840160005b83811015613e2757815187529582019590820190600101613e0b565b509495945050505050565b848152613e426020820185613abd565b608060408201526000613e586080830185613af5565b828103606084015261189a8185613df6565b634e487b7160e01b600052603260045260246000fd5b600060208284031215613e9257600080fd5b8151600981106102b457600080fd5b6020810160098310613eb557613eb5613aa7565b91905290565b6001600160a01b0381168114613ed057600080fd5b50565b600060208284031215613ee557600080fd5b81516102b481613ebb565b608080825285518282018190526000919060209060a0850190828a01855b82811015613f5257613f42848351805182526020810151602083015260408101516040830152606081015160608301525050565b9285019290840190600101613f0e565b5050508481036020860152613f678189613af5565b925050508281036040840152613f7d8186613df6565b9050828103606084015261189a8185613df6565b600060808284031215613fa357600080fd5b613fab613bb0565b825181526020830151602082015260408301516040820152606083015160608201528091505092915050565b805160ff8116811461200457600080fd5b600080600060608486031215613ffd57600080fd5b835161400881613ebb565b6020850151909350915061401e60408501613fd7565b90509250925092565b805169ffffffffffffffffffff8116811461200457600080fd5b600080600080600060a0868803121561405957600080fd5b61406286614027565b945060208601519350604086015192506060860151915061408560808701614027565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b8181038181111561011657610116614091565b60008060008060008060c087890312156140d357600080fd5b86516140de81613ebb565b60208801519096506140ef81613ebb565b94506140fd60408801613fd7565b935061410b60608801613fd7565b9250608087015161411b81613ebb565b60a088015190925063ffffffff8116811461413557600080fd5b809150509295509295509295565b6020808252825182820181905260009190848201906040850190845b8181101561418157835163ffffffff168352928401929184019160010161415f565b50909695505050505050565b600082601f83011261419e57600080fd5b815160206141ae613c4f83613c0a565b8083825260208201915060208460051b8701019350868411156141d057600080fd5b602086015b84811015613b8f5780516141e881613ebb565b83529183019183016141d5565b6000806040838503121561420857600080fd5b825167ffffffffffffffff8082111561422057600080fd5b818501915085601f83011261423457600080fd5b81516020614244613c4f83613c0a565b82815260059290921b8401810191818101908984111561426357600080fd5b948201945b838610156142915785518060060b81146142825760008081fd5b82529482019490820190614268565b918801519196509093505050808211156142aa57600080fd5b506142b78582860161418d565b9150509250929050565b600682810b9082900b03667fffffffffffff198112667fffffffffffff8213171561011657610116614091565b634e487b7160e01b600052601260045260246000fd5b60008160060b8360060b8061431b5761431b6142ee565b667fffffffffffff1982146000198214161561433957614339614091565b90059392505050565b600082614351576143516142ee565b500790565b60008160020b627fffff19810361436f5761436f614091565b6000190192915050565b600181815b808511156143b457816000190482111561439a5761439a614091565b808516156143a757918102915b93841c939080029061437e565b509250929050565b6000826143cb57506001610116565b816143d857506000610116565b81600181146143ee57600281146143f857614414565b6001915050610116565b60ff84111561440957614409614091565b50506001821b610116565b5060208310610133831016604e8410600b8410161715614437575081810a610116565b6144418383614379565b806000190482111561445557614455614091565b029392505050565b60006102b460ff8416836143bc565b818103600083128015838313168383128216171561448c5761448c614091565b5092915050565b6000600160ff1b82016144a8576144a8614091565b5060000390565b8051801515811461200457600080fd5b6000806000606084860312156144d457600080fd5b83516144df81613ebb565b6020850151909350915061401e604085016144af565b60006080828403121561450757600080fd5b61450f613bb0565b82518060070b811461452057600080fd5b8152602083015167ffffffffffffffff8116811461453d57600080fd5b60208201526040830151600381900b811461455757600080fd5b60408201526060928301519281019290925250919050565b808201828112600083128015821682158216171561458f5761458f614091565b505092915050565b6000806000606084860312156145ac57600080fd5b83516145b781613ebb565b602085015160409095015190969495509392505050565b60ff8416815267ffffffffffffffff831660208201526060604082015260006145fa6060830184613df6565b95945050505050565b6001600160a01b03831681526040602082018190526000906102ce90830184613af5565b60006020828403121561463957600080fd5b5051919050565b60008261464f5761464f6142ee565b600160ff1b82146000198414161561466957614669614091565b500590565b6146788185613abd565b60606020820152600061468e6060830185613af5565b8281036040840152610f4f8185613df6565b601f8211156146e8576000816000526020600020601f850160051c810160208610156146c95750805b601f850160051c820191505b8181101561325c578281556001016146d5565b505050565b815167ffffffffffffffff81111561470757614707613b9a565b61471b816147158454613dc2565b846146a0565b602080601f83116001811461475057600084156147385750858301515b600019600386901b1c1916600185901b17855561325c565b600085815260208120601f198616915b8281101561477f57888601518255948401946001909101908401614760565b508582101561479d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082018082111561011657610116614091565b6000826147cf576147cf6142ee565b500490565b6000826147e3576147e36142ee565b500690565b80820260008212600160ff1b8414161561480457614804614091565b818105831482151761011657610116614091565b600069ffffffffffffffffffff82168061436f5761436f614091565b60006001820161484657614846614091565b5060010190565b60006102b483836143bc565b808202811582820484141761011657610116614091565b60006020828403121561488257600080fd5b6102b4826144af565b60006020828403121561489d57600080fd5b6102b482613fd7565b60006001600160ff1b01820161484657614846614091565b6000600160ff1b82016148d3576148d3614091565b506000190190565b60008160020b627fffff1981036148f4576148f4614091565b60000392915050565b6000825161490f818460208701613ad1565b919091019291505056fea264697066735822122074f32fef384fdc296b0859f1c1f941c8e736c6cb972aa9e2b894956ebd6a80b364736f6c63430008160033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xbc73db80bf4b8784ba10a8910a0b7ef85f6846d102b41dd990969ea205335354"}}],"ommers":[]},{"header":{"parentHash":"0x026ae0c6ae91f186a9befa1ac8be30eea35e30e77de51a731085221e5cd39209","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x6e4969a136061ca7a390d12830d47a151585325a8d396819fb2b958ff85e9f8f","receiptsRoot":"0xc3e81df67d3e2a6c8345a954ef250cfcc41abcc2292a5aa263071124533fc9ad","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x3c0f6","timestamp":"0x66b200ce","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x18993a68","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3c0f6","maxFeePerGas":"0x5d4285cd","maxPriorityFeePerGas":"0x3b9aca00","value":"0x0","accessList":[],"input":"0x608060405234801561001057600080fd5b50610380806100206000396000f3fe6080604052600080357fffffffff0000000000000000000000000000000000000000000000000000000016905060008160e01c610251565b60006379ba509782101561015e5781631627540c811461009857632a952b2d81146100b457633659cfe681146100d0576350c946fe81146100ec576353a47bb781146101085763625ca21c81146101245763718fe928811461014057610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc9150610158565b738138ef7cf908021d117e542120b7a390650161079150610158565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc91505b5061024c565b816379ba509781146101a657638da5cb5b81146101c25763aaf10f4281146101de5763c7f62cda81146101fa5763daa250be81146102165763deba1b9881146102325761024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b7347d08dad17ccb558b3ea74b1a0e73a9cc804a9dc915061024a565b738138ef7cf908021d117e542120b7a39065016107915061024a565b738138ef7cf908021d117e542120b7a3906501610791505b505b919050565b61025a81610037565b915050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036102ce57816040517fc2a825f50000000000000000000000000000000000000000000000000000000081526004016102c5919061032f565b60405180910390fd5b3660008037600080366000845af43d6000803e80600081146102ef573d6000f35b3d6000fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b610329816102f4565b82525050565b60006020820190506103446000830184610320565b9291505056fea264697066735822122017a4b7fdaaab3897a7b47abaed8d2ee92d558883d3bb2a8454f9601b2ab2c3db64736f6c63430008150033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x2476e039803622aeb040f924f04c493f559aed3d6c9372ab405cb33c8c695328"}}],"ommers":[]},{"header":{"parentHash":"0x3d22100ac0ee8d5cde334f7f926191a861b0648971ebc179547df28a0224c6d0","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9511d4711e5c30a72b0bff38a261daa75dcc5ba8b772d970a5c742244b4c861b","transactionsRoot":"0xba5fff578d3d6c2cd63acbe9bca353eaa6fe22a5c408956eff49106e0a96c507","receiptsRoot":"0xbae111f01cb07677e3a8c5031546138407c01bc964d3493d732dc4edf47d36d3","logsBloom":"0x00000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000020000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000001000000000000000000000400000001000010000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x5","gasLimit":"0x1c9c380","gasUsed":"0xcae7","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x12e09c7a","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xcc4d","maxFeePerGas":"0x557e5ec4","maxPriorityFeePerGas":"0x3b9aca00","to":"0x83a0444b93927c3afcbe46e522280390f748e171","value":"0x0","accessList":[],"input":"0x3659cfe6000000000000000000000000108f53faf774d7c4c56f5bce9ca6e605ce8aeadd","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xf88e7b19ee347145c257e0cf7ac4ecc2bae83ca79d7edaa231e71d3213aeb151"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x9c8eaf493f8b4edce2ba1647343eadcc0989cf461e712c0a6253ff2ca1842bb7","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xdd07c07470e1deff3749831f0f1ad8d4b6e35505e83b3c6ea14181716197cd8a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x24a1ab52","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200c9","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xf6930be4847cac5017bbcbec2756eed19f36b4196526a98a88e311c296e3a9be","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x29aa352e71b139e83b397bdd3dcf9b65d74770edaf3a9624d0dbc4f96f868680","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200cc","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x200d75e8","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xb6003e7ba07a15a9e35f63daa484728ec4ceeded0c4d10ac1b04e9552d412b3c","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x4","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1592fbf9","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x149d41e3b89d8324cef3feff98ef308e97bafe8745cc8461c60172bc7d4c44ba","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x0b44110186e52ff0ceb6b0776ca2992c94144a4ed712eef65ea038260ef0fcc7","receiptsRoot":"0xc2823b8eb4730d9f2657137cc2ddc2c4f22ab68e0ab826236cf6a1551ca2b3a5","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0xe61f9","timestamp":"0x66b200cb","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342770c0","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0xe94d1","maxFeePerGas":"0x83215600","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060008061002661006d60201b61081b1760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050610141565b60008060405160200161007f90610121565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b600061010b60238361009e565b9150610116826100af565b604082019050919050565b6000602082019050818103600083015261013a816100fe565b9050919050565b611000806101506000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c806379ba50971161005b57806379ba5097146100ed5780638da5cb5b146100f7578063aaf10f4214610115578063c7f62cda1461013357610088565b80631627540c1461008d5780633659cfe6146100a957806353a47bb7146100c5578063718fe928146100e3575b600080fd5b6100a760048036038101906100a29190610d25565b61014f565b005b6100c360048036038101906100be9190610d25565b6102d0565b005b6100cd6102e4565b6040516100da9190610d61565b60405180910390f35b6100eb610317565b005b6100f56103fe565b005b6100ff61058b565b60405161010c9190610d61565b60405180910390f35b61011d6105be565b60405161012a9190610d61565b60405180910390f35b61014d60048036038101906101489190610d25565b6105f1565b005b61015761084c565b600061016161081b565b9050600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036101c9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610252576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce22826040516102c49190610d61565b60405180910390a15050565b6102d861084c565b6102e1816108c5565b50565b60006102ee61081b565b60010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600061032161081b565b90503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146103b757336040517fa0e5a0d70000000000000000000000000000000000000000000000000000000081526004016103ae9190610d61565b60405180910390fd5b60008160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600061040861081b565b905060008160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104a357336040517fa0e5a0d700000000000000000000000000000000000000000000000000000000815260040161049a9190610d61565b60405180910390fd5b7fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c8260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516104f8929190610d7c565b60405180910390a1808260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008260010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b600061059561081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105c8610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60006105fb610b05565b905060018160000160146101000a81548160ff02191690831515021790555060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008373ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff16633659cfe6846040516024016106cc9190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161071b9190610e16565b600060405180830381855af49150503d8060008114610756576040519150601f19603f3d011682016040523d82523d6000602084013e61075b565b606091505b505090508015806107c357508173ffffffffffffffffffffffffffffffffffffffff16610786610b05565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614155b156107fa576040517fa1cfa5a800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360000160146101000a81548160ff0219169083151502179055600080fd5b60008060405160200161082d90610eb0565b6040516020818303038152906040528051906020012090508091505090565b610854610b36565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108c357336040517f8e4a23d60000000000000000000000000000000000000000000000000000000081526004016108ba9190610d61565b60405180910390fd5b565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361092b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61093481610b69565b61097557806040517f8a8b41ec00000000000000000000000000000000000000000000000000000000815260040161096c9190610d61565b60405180910390fd5b600061097f610b05565b90508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610a0a576040517fa88ee57700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060000160149054906101000a900460ff16158015610a2e5750610a2d82610b7c565b5b15610a7057816040517f15504301000000000000000000000000000000000000000000000000000000008152600401610a679190610d61565b60405180910390fd5b818160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503073ffffffffffffffffffffffffffffffffffffffff167f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c783604051610af99190610d61565b60405180910390a25050565b600080604051602001610b1790610f42565b6040516020818303038152906040528051906020012090508091505090565b6000610b4061081b565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080823b905060008111915050919050565b60008060003073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1663c7f62cda86604051602401610bc59190610d61565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610c149190610e16565b600060405180830381855af49150503d8060008114610c4f576040519150601f19603f3d011682016040523d82523d6000602084013e610c54565b606091505b509150915081158015610cb9575063a1cfa5a860e01b604051602001610c7a9190610faf565b6040516020818303038152906040528051906020012081604051602001610ca19190610e16565b60405160208183030381529060405280519060200120145b92505050919050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610cf282610cc7565b9050919050565b610d0281610ce7565b8114610d0d57600080fd5b50565b600081359050610d1f81610cf9565b92915050565b600060208284031215610d3b57610d3a610cc2565b5b6000610d4984828501610d10565b91505092915050565b610d5b81610ce7565b82525050565b6000602082019050610d766000830184610d52565b92915050565b6000604082019050610d916000830185610d52565b610d9e6020830184610d52565b9392505050565b600081519050919050565b600081905092915050565b60005b83811015610dd9578082015181840152602081019050610dbe565b60008484015250505050565b6000610df082610da5565b610dfa8185610db0565b9350610e0a818560208601610dbb565b80840191505092915050565b6000610e228284610de5565b915081905092915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b6000610e9a602383610e2d565b9150610ea582610e3e565b604082019050919050565b60006020820190508181036000830152610ec981610e8d565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b6000610f2c602183610e2d565b9150610f3782610ed0565b604082019050919050565b60006020820190508181036000830152610f5b81610f1f565b9050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6000819050919050565b610fa9610fa482610f62565b610f8e565b82525050565b6000610fbb8284610f98565b6004820191508190509291505056fea264697066735822122023a7c33d7b91dce35ffbcf8837693364ab22a3905d0fc00016833e5fac45ca2f64736f6c63430008110033","r":"0x1","s":"0x1","yParity":"0x0","hash":"0x4feae6769d748b4f0f7c9bf21d782236c88f13906789a3ec602961296e4c3e43"}}],"ommers":[]},{"header":{"parentHash":"0xb3535af5103fd1c2bbd6dc7ff23f0799037a6542c231ebcb85abd776560fa512","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x23d74fb99ff6e42cbb5c33f92b078e37be6af2b6092459b103ff7059a6517ebc","transactionsRoot":"0x9eab45eca206fe11c107ea985c7d02fcfa442836aea3e04ba11dc4df587d5aa6","receiptsRoot":"0xe25abcfa973db8c55f73292137c626430de130a382ad4466337fefb0f7c8fde0","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x3ce3f","timestamp":"0x66b200cd","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x1c0bc72b","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x343a","nonce":"0x0","gas":"0x3d8a8","maxFeePerGas":"0x6211577c","maxPriorityFeePerGas":"0x3b9aca00","to":"0x4e59b44847b379578588920ca78fbf26c0b4956c","value":"0x0","accessList":[],"input":"0x4786e4342646b3ba97c1790b6cf5a55087a36240b22570f5d3a5d6bcc929d93b608060405234801561001057600080fd5b5060405161068538038061068583398181016040528101906100329190610275565b818181600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361009b576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6100ae8161019d60201b61004f1760201c565b6100ef57806040517f8a8b41ec0000000000000000000000000000000000000000000000000000000081526004016100e691906102c4565b60405180910390fd5b806100fe6101b060201b60201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050806101536101e160201b6100621760201c565b60000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050505050610414565b600080823b905060008111915050919050565b6000806040516020016101c290610362565b6040516020818303038152906040528051906020012090508091505090565b6000806040516020016101f3906103f4565b6040516020818303038152906040528051906020012090508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061024282610217565b9050919050565b61025281610237565b811461025d57600080fd5b50565b60008151905061026f81610249565b92915050565b6000806040838503121561028c5761028b610212565b5b600061029a85828601610260565b92505060206102ab85828601610260565b9150509250929050565b6102be81610237565b82525050565b60006020820190506102d960008301846102b5565b92915050565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b600061034c6021836102df565b9150610357826102f0565b604082019050919050565b6000602082019050818103600083015261037b8161033f565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006103de6023836102df565b91506103e982610382565b604082019050919050565b6000602082019050818103600083015261040d816103d1565b9050919050565b610262806104236000396000f3fe6080604052366100135761001161001d565b005b61001b61001d565b005b6000610027610093565b90503660008037600080366000845af43d6000803e806000811461004a573d6000f35b3d6000fd5b600080823b905060008111915050919050565b6000806040516020016100749061017a565b6040516020818303038152906040528051906020012090508091505090565b600061009d6100c6565b60000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000806040516020016100d89061020c565b6040516020818303038152906040528051906020012090508091505090565b600082825260208201905092915050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e4f776e6160008201527f626c650000000000000000000000000000000000000000000000000000000000602082015250565b60006101646023836100f7565b915061016f82610108565b604082019050919050565b6000602082019050818103600083015261019381610157565b9050919050565b7f696f2e73796e7468657469782e636f72652d636f6e7472616374732e50726f7860008201527f7900000000000000000000000000000000000000000000000000000000000000602082015250565b60006101f66021836100f7565b91506102018261019a565b604082019050919050565b60006020820190508181036000830152610225816101e9565b905091905056fea2646970667358221220800da1f73cebd5e4afa07496d9bca6b6c4f526bdd3f4014ec15c70fe3a1c441364736f6c6343000811003300000000000000000000000047d08dad17ccb558b3ea74b1a0e73a9cc804a9dc000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266","r":"0x1","s":"0x1","yParity":"0x0","hash":"0xb6794d5c7abed6f91d447e8efb72ef2580595a6d7c8dee57ba1dbb330970146a"}}],"ommers":[]},{"header":{"parentHash":"0x08abe6e453727534d8dd708843a7522b7d500338bdfe2402ca105dcdb05eebe9","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x510f2275449c013534a25ad0b13c867caf720947b68bcbcd4863f7b172a5d023","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x3","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66b200ca","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x29dd5614","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]}]} \ No newline at end of file diff --git a/crates/anvil/test-data/state-dump-legacy.json b/crates/anvil/test-data/state-dump-legacy.json index 273442701292e..26fa019b20fb5 100644 --- a/crates/anvil/test-data/state-dump-legacy.json +++ b/crates/anvil/test-data/state-dump-legacy.json @@ -1 +1 @@ -{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdc823","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xb92480171c0235f8c6710a4047d7ee14a3be58c630839fb4422826ff3a013e44","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc823","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}}],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdc80e","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xa00dc0c9ee9a888e67ea32d8772f8cc28eff62448c9ec985ee941fcbc921ba59","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc814","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}}],"ommers":[]}]} \ No newline at end of file +{"block":{"number":2,"beneficiary":"0x0000000000000000000000000000000000000000","timestamp":1724762147,"gas_limit":30000000,"basefee":875175000,"difficulty":"0x0","prevrandao":"0xb92480171c0235f8c6710a4047d7ee14a3be58c630839fb4422826ff3a013e44","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":2,"blocks":[{"header":{"parentHash":"0xceb0fe420d6f14a8eeec4319515b89acbb0bb4861cad9983d529ab4b1e4af929","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc823","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}}],"ommers":[]},{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdc80e","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0xa00dc0c9ee9a888e67ea32d8772f8cc28eff62448c9ec985ee941fcbc921ba59","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdc814","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}}],"ommers":[]}]} \ No newline at end of file diff --git a/crates/anvil/test-data/state-dump.json b/crates/anvil/test-data/state-dump.json index e868bf2efea51..4b7e66b17f56d 100644 --- a/crates/anvil/test-data/state-dump.json +++ b/crates/anvil/test-data/state-dump.json @@ -1 +1 @@ -{"block":{"number":"0x2","coinbase":"0x0000000000000000000000000000000000000000","timestamp":"0x66cdcc2b","gas_limit":"0x1c9c380","basefee":"0x342a1c58","difficulty":"0x0","prevrandao":"0xdb639d7f8af4f0ff2aa9cc49861820e72f5f8bfeeed677d1e3569f6b1625df4a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":"0x2","blocks":[{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdcc25","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x3a52101c98a4319c419681131d3585d70a6cf13a9af25136be20d451eed5480a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc29","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}},"impersonated_sender":null}],"ommers":[]},{"header":{"parentHash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc2b","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}},"impersonated_sender":null}],"ommers":[]}],"transactions":[{"info":{"transaction_hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3","transaction_index":0,"from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","block_number":1},{"info":{"transaction_hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515","transaction_index":0,"from":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","address":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x1f435a603c1bf6d544a90156b572b96d7a1730028422d800839bae78bb3506d0","block_number":2}]} \ No newline at end of file +{"block":{"number":2,"beneficiary":"0x0000000000000000000000000000000000000000","timestamp":1724763179,"gas_limit":30000000,"basefee":875175000,"difficulty":"0x0","prevrandao":"0xdb639d7f8af4f0ff2aa9cc49861820e72f5f8bfeeed677d1e3569f6b1625df4a","blob_excess_gas_and_price":{"excess_blob_gas":0,"blob_gasprice":1}},"accounts":{"0x0000000000000000000000000000000000000000":{"nonce":0,"balance":"0xa410","code":"0x","storage":{}},"0x14dc79964da2c08b23698b3d3cc7ca32193d9955":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x15d34aaf54267db7d7c367839aaf71a00a2c6a65":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x23618e81e3f5cdf7f54c3d65f7fbc0abf5b21e8f":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x3c44cdddb6a900fa2b585dd299e03d12fa4293bc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x4e59b44847b379578588920ca78fbf26c0b4956c":{"nonce":0,"balance":"0x0","code":"0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3","storage":{}},"0x70997970c51812dc3a010c7d01b50e0d17dc79c8":{"nonce":1,"balance":"0x21e19e0b90393da9b38","code":"0x","storage":{}},"0x90f79bf6eb2c4f870365e785982e1f101e93b906":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x976ea74026e726554db657fa54763abd0c3a0aa9":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0x9965507d1a55bcc2695c58ba16fb37d819b0a4dc":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xa0ee7a142d267c1f36714e4a8f75612f20a79720":{"nonce":0,"balance":"0x21e19e0c9bab2400000","code":"0x","storage":{}},"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266":{"nonce":1,"balance":"0x21e19e0b6a140b55df8","code":"0x","storage":{}}},"best_block_number":2,"blocks":[{"header":{"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","receiptsRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x0","gasLimit":"0x1c9c380","gasUsed":"0x0","timestamp":"0x66cdcc25","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[],"ommers":[]},{"header":{"parentHash":"0x3a52101c98a4319c419681131d3585d70a6cf13a9af25136be20d451eed5480a","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0x6e5f60b37eeaece7dedfc42cc394731a0ae3ed3d3be93c402780b2e23e141175","transactionsRoot":"0x9ceaeb1b16b924afbf4bf4df4c2c49dc9cfbe23ac7a40bf26a704158ea2d352f","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x1","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc29","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x3b9aca00","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","value":"0x0","accessList":[],"input":"0x","r":"0x703a4b4d6dbff2fa2345df73263df2098faa7214863b5ec82c4c07162d87b853","s":"0x17dea762c4ce600ad1d9d2c9ae6dd35b9e526d03c875f868ad0792fd4fad72e0","yParity":"0x0","hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3"}},"impersonated_sender":null}],"ommers":[]},{"header":{"parentHash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","miner":"0x0000000000000000000000000000000000000000","stateRoot":"0xe1423fd180478ab4fd05a7103277d64496b15eb914ecafe71eeec871b552efd1","transactionsRoot":"0x2b5598ef261e5f88e4303bb2b3986b3d5c0ebf4cd9977daebccae82a6469b988","receiptsRoot":"0xf78dfb743fbd92ade140711c8bbc542b5e307f0ab7984eff35d751969fe57efa","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","difficulty":"0x0","number":"0x2","gasLimit":"0x1c9c380","gasUsed":"0x5208","timestamp":"0x66cdcc2b","mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000","nonce":"0x0000000000000000","baseFeePerGas":"0x342a1c58","blobGasUsed":"0x0","excessBlobGas":"0x0","extraData":"0x"},"transactions":[{"transaction":{"EIP1559":{"chainId":"0x7a69","nonce":"0x0","gas":"0x5209","maxFeePerGas":"0x77359401","maxPriorityFeePerGas":"0x1","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","value":"0x0","accessList":[],"input":"0x","r":"0x85c2794a580da137e24ccc823b45ae5cea99371ae23ee13860fcc6935f8305b0","s":"0x41de7fa4121dab284af4453d30928241208bafa90cdb701fe9bc7054759fe3cd","yParity":"0x0","hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515"}},"impersonated_sender":null}],"ommers":[]}],"transactions":[{"info":{"transaction_hash":"0xf8d5fb22350f52ae8c30cd7f6969eb73de849c8dc010f4215d4c5c24824fe2b3","transaction_index":0,"from":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","to":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","address":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x0d575f9ca968cd483549172245483a12343afc3cabef80f0fa39855b10b98c70","block_number":1},{"info":{"transaction_hash":"0x8c9b68e8947ace33028dba167354fde369ed7bbe34911b772d09b3c64b861515","transaction_index":0,"from":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","to":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","contract_address":null,"traces":[{"parent":null,"children":[],"idx":0,"trace":{"depth":0,"success":true,"caller":"0x70997970c51812dc3a010c7d01b50e0d17dc79c8","address":"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266","maybe_precompile":null,"selfdestruct_refund_target":null,"selfdestruct_transferred_value":null,"kind":"CALL","value":"0x0","data":"0x","output":"0x","gas_used":0,"gas_limit":1,"status":"Stop","steps":[],"decoded":{"label":null,"return_data":null,"call_data":null}},"logs":[],"ordering":[]}],"exit":"Stop","out":"0x","nonce":0,"gas_used":21000},"receipt":{"type":"0x2","status":"0x1","cumulativeGasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"block_hash":"0x1f435a603c1bf6d544a90156b572b96d7a1730028422d800839bae78bb3506d0","block_number":2}]} \ No newline at end of file diff --git a/crates/anvil/tests/it/anvil_api.rs b/crates/anvil/tests/it/anvil_api.rs index 22179d505a9b6..68d4550d6bbd6 100644 --- a/crates/anvil/tests/it/anvil_api.rs +++ b/crates/anvil/tests/it/anvil_api.rs @@ -30,7 +30,7 @@ use anvil_core::{ }, types::{ReorgOptions, TransactionData}, }; -use foundry_evm::revm::primitives::SpecId; +use revm::primitives::hardfork::SpecId; use std::{ future::IntoFuture, str::FromStr, diff --git a/crates/anvil/tests/it/fork.rs b/crates/anvil/tests/it/fork.rs index cda5fc805cf8c..a0bc8aa05cff1 100644 --- a/crates/anvil/tests/it/fork.rs +++ b/crates/anvil/tests/it/fork.rs @@ -61,7 +61,7 @@ pub fn fork_config() -> NodeConfig { #[tokio::test(flavor = "multi_thread")] async fn test_fork_gas_limit_applied_from_config() { - let (api, _handle) = spawn(fork_config().with_gas_limit(Some(10_000_000_u128))).await; + let (api, _handle) = spawn(fork_config().with_gas_limit(Some(10_000_000))).await; assert_eq!(api.gas_limit(), uint!(10_000_000_U256)); } @@ -1329,6 +1329,7 @@ async fn test_immutable_fork_transaction_hash() { use std::str::FromStr; // Fork to a block with a specific transaction + // let fork_tx_hash = TxHash::from_str("2ac736ce725d628ef20569a1bb501726b42b33f9d171f60b92b69de3ce705845") .unwrap(); diff --git a/crates/anvil/tests/it/gas.rs b/crates/anvil/tests/it/gas.rs index 623654537d3d2..f3bcd01ddfe47 100644 --- a/crates/anvil/tests/it/gas.rs +++ b/crates/anvil/tests/it/gas.rs @@ -8,7 +8,7 @@ use alloy_rpc_types::{BlockId, TransactionRequest}; use alloy_serde::WithOtherFields; use anvil::{eth::fees::INITIAL_BASE_FEE, spawn, NodeConfig}; -const GAS_TRANSFER: u128 = 21_000; +const GAS_TRANSFER: u64 = 21_000; #[tokio::test(flavor = "multi_thread")] async fn test_gas_limit_applied_from_config() { diff --git a/crates/anvil/tests/it/state.rs b/crates/anvil/tests/it/state.rs index d642582269e68..95bdddf57f566 100644 --- a/crates/anvil/tests/it/state.rs +++ b/crates/anvil/tests/it/state.rs @@ -2,7 +2,7 @@ use crate::abi::Greeter; use alloy_network::{ReceiptResponse, TransactionBuilder}; -use alloy_primitives::{address, utils::Unit, Bytes, Uint, U256, U64}; +use alloy_primitives::{address, utils::Unit, Bytes, Uint, U256}; use alloy_provider::Provider; use alloy_rpc_types::{BlockId, TransactionRequest}; use alloy_serde::WithOtherFields; @@ -262,7 +262,7 @@ async fn test_fork_load_state_with_greater_state_block() { let serialized_state = api.serialized_state(false).await.unwrap(); - assert_eq!(serialized_state.best_block_number, Some(block_number.to::())); + assert_eq!(serialized_state.best_block_number, Some(block_number.to::())); let (api, _handle) = spawn( NodeConfig::test() diff --git a/crates/anvil/tests/it/traces.rs b/crates/anvil/tests/it/traces.rs index 297f188f7ddbd..849956cabe5dd 100644 --- a/crates/anvil/tests/it/traces.rs +++ b/crates/anvil/tests/it/traces.rs @@ -138,7 +138,11 @@ async fn test_transfer_debug_trace_call() { let traces = handle .http_provider() - .debug_trace_call(tx, BlockId::latest(), GethDebugTracingCallOptions::default()) + .debug_trace_call( + WithOtherFields::new(tx), + BlockId::latest(), + GethDebugTracingCallOptions::default(), + ) .await .unwrap(); @@ -183,7 +187,7 @@ async fn test_call_tracer_debug_trace_call() { let internal_call_tx_traces = handle .http_provider() .debug_trace_call( - internal_call_tx.clone(), + WithOtherFields::new(internal_call_tx.clone()), BlockId::latest(), GethDebugTracingCallOptions::default().with_tracing_options( GethDebugTracingOptions::default() @@ -211,7 +215,7 @@ async fn test_call_tracer_debug_trace_call() { let internal_call_only_top_call_tx_traces = handle .http_provider() .debug_trace_call( - internal_call_tx.clone(), + WithOtherFields::new(internal_call_tx.clone()), BlockId::latest(), GethDebugTracingCallOptions::default().with_tracing_options( GethDebugTracingOptions::default() @@ -240,7 +244,7 @@ async fn test_call_tracer_debug_trace_call() { let direct_call_tx_traces = handle .http_provider() .debug_trace_call( - direct_call_tx, + WithOtherFields::new(direct_call_tx), BlockId::latest(), GethDebugTracingCallOptions::default().with_tracing_options( GethDebugTracingOptions::default() @@ -284,7 +288,7 @@ async fn test_debug_trace_call_state_override() { let tx_traces = handle .http_provider() .debug_trace_call( - tx.clone(), + WithOtherFields::new(tx.clone()), BlockId::latest(), GethDebugTracingCallOptions::default() .with_tracing_options(GethDebugTracingOptions::default()) diff --git a/crates/anvil/tests/it/transaction.rs b/crates/anvil/tests/it/transaction.rs index 4c58170454601..d01bfa02aa3af 100644 --- a/crates/anvil/tests/it/transaction.rs +++ b/crates/anvil/tests/it/transaction.rs @@ -237,7 +237,7 @@ async fn can_mine_large_gas_limit() { let from = accounts[0].address(); let to = accounts[1].address(); - let gas_limit = anvil::DEFAULT_GAS_LIMIT as u64; + let gas_limit = anvil::DEFAULT_GAS_LIMIT; let amount = handle.genesis_balance().checked_div(U256::from(3u64)).unwrap(); let tx = diff --git a/crates/cast/Cargo.toml b/crates/cast/Cargo.toml index fc6e4368a8d8f..23315bfa30f2b 100644 --- a/crates/cast/Cargo.toml +++ b/crates/cast/Cargo.toml @@ -26,6 +26,7 @@ foundry-block-explorers.workspace = true foundry-common.workspace = true foundry-compilers.workspace = true foundry-config.workspace = true +foundry-evm-core.workspace = true foundry-evm.workspace = true foundry-wallets.workspace = true @@ -55,6 +56,7 @@ alloy-transport.workspace = true chrono.workspace = true eyre.workspace = true futures.workspace = true +revm.workspace = true rand.workspace = true rayon.workspace = true serde_json.workspace = true diff --git a/crates/cast/src/cmd/call.rs b/crates/cast/src/cmd/call.rs index b005a8af0f8c8..7499efe0ccee9 100644 --- a/crates/cast/src/cmd/call.rs +++ b/crates/cast/src/cmd/call.rs @@ -30,6 +30,7 @@ use foundry_evm::{ traces::{InternalTraceMode, TraceMode}, }; use regex::Regex; +use revm::context::TransactionType; use std::{str::FromStr, sync::LazyLock}; // matches override pattern
:: @@ -242,8 +243,8 @@ impl CallArgs { TracingExecutor::get_fork_material(&config, evm_opts).await?; // modify settings that usually set in eth_call - env.cfg.disable_block_gas_limit = true; - env.block.gas_limit = U256::MAX; + env.evm_env.cfg_env.disable_block_gas_limit = true; + env.evm_env.block_env.gas_limit = u64::MAX; let trace_mode = TraceMode::Call .with_debug(debug) @@ -265,9 +266,18 @@ impl CallArgs { let value = tx.value.unwrap_or_default(); let input = tx.inner.input.into_input().unwrap_or_default(); let tx_kind = tx.inner.to.expect("set by builder"); + let env_tx = &mut executor.env_mut().tx; + + if let Some(tx_type) = tx.inner.transaction_type { + env_tx.tx_type = tx_type; + } if let Some(access_list) = tx.inner.access_list { - executor.env_mut().tx.access_list = access_list.0 + env_tx.access_list = access_list; + + if env_tx.tx_type == TransactionType::Legacy as u8 { + env_tx.tx_type = TransactionType::Eip2930 as u8; + } } let trace = match tx_kind { diff --git a/crates/cast/src/cmd/run.rs b/crates/cast/src/cmd/run.rs index 90470ef31ed97..c586cf4c9ded4 100644 --- a/crates/cast/src/cmd/run.rs +++ b/crates/cast/src/cmd/run.rs @@ -1,9 +1,5 @@ -use crate::{ - revm::primitives::EnvWithHandlerCfg, utils::apply_chain_and_block_specific_env_changes, -}; use alloy_consensus::Transaction; use alloy_network::{AnyNetwork, TransactionResponse}; -use alloy_primitives::U256; use alloy_provider::Provider; use alloy_rpc_types::BlockTransactions; use clap::Parser; @@ -27,7 +23,11 @@ use foundry_evm::{ opts::EvmOpts, traces::{InternalTraceMode, TraceMode}, utils::configure_tx_env, + Env, }; +use foundry_evm_core::env::AsEnvMut; + +use crate::utils::apply_chain_and_block_specific_env_changes; /// CLI arguments for `cast run`. #[derive(Clone, Debug, Parser)] @@ -149,16 +149,16 @@ impl RunArgs { TracingExecutor::get_fork_material(&config, evm_opts).await?; let mut evm_version = self.evm_version; - env.cfg.disable_block_gas_limit = self.disable_block_gas_limit; - env.block.number = U256::from(tx_block_number); + env.evm_env.cfg_env.disable_block_gas_limit = self.disable_block_gas_limit; + env.evm_env.block_env.number = tx_block_number; if let Some(block) = &block { - env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.beneficiary; - env.block.difficulty = block.header.difficulty; - env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); - env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); - env.block.gas_limit = U256::from(block.header.gas_limit); + env.evm_env.block_env.timestamp = block.header.timestamp; + env.evm_env.block_env.beneficiary = block.header.beneficiary; + env.evm_env.block_env.difficulty = block.header.difficulty; + env.evm_env.block_env.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); + env.evm_env.block_env.basefee = block.header.base_fee_per_gas.unwrap_or_default(); + env.evm_env.block_env.gas_limit = block.header.gas_limit; // TODO: we need a smarter way to map the block to the corresponding evm_version for // commonly used chains @@ -168,7 +168,7 @@ impl RunArgs { evm_version = Some(EvmVersion::Cancun); } } - apply_chain_and_block_specific_env_changes::(&mut env, block); + apply_chain_and_block_specific_env_changes::(env.as_env_mut(), block); } let trace_mode = TraceMode::Call @@ -187,8 +187,12 @@ impl RunArgs { odyssey, create2_deployer, )?; - let mut env = - EnvWithHandlerCfg::new_with_spec_id(Box::new(env.clone()), executor.spec_id()); + let mut env = Env::new_with_spec_id( + env.evm_env.cfg_env.clone(), + env.evm_env.block_env.clone(), + env.tx.clone(), + executor.spec_id(), + ); // Set the state to the moment right before the transaction if !self.quick { @@ -218,7 +222,7 @@ impl RunArgs { break; } - configure_tx_env(&mut env, &tx.inner); + configure_tx_env(&mut env.as_env_mut(), &tx.inner); if let Some(to) = Transaction::to(tx) { trace!(tx=?tx.tx_hash(),?to, "executing previous call transaction"); @@ -226,7 +230,7 @@ impl RunArgs { format!( "Failed to execute transaction: {:?} in block {}", tx.tx_hash(), - env.block.number + env.evm_env.block_env.number ) })?; } else { @@ -240,7 +244,7 @@ impl RunArgs { format!( "Failed to deploy transaction: {:?} in block {}", tx.tx_hash(), - env.block.number + env.evm_env.block_env.number ) }) } @@ -257,7 +261,7 @@ impl RunArgs { let result = { executor.set_trace_printer(self.trace_printer); - configure_tx_env(&mut env, &tx.inner); + configure_tx_env(&mut env.as_env_mut(), &tx.inner); if let Some(to) = Transaction::to(&tx) { trace!(tx=?tx.tx_hash(), to=?to, "executing call transaction"); diff --git a/crates/cast/src/cmd/wallet/mod.rs b/crates/cast/src/cmd/wallet/mod.rs index 52d24c01b6941..fb6e15dc56567 100644 --- a/crates/cast/src/cmd/wallet/mod.rs +++ b/crates/cast/src/cmd/wallet/mod.rs @@ -1,8 +1,8 @@ -use crate::revm::primitives::Authorization; use alloy_chains::Chain; use alloy_dyn_abi::TypedData; use alloy_primitives::{hex, Address, PrimitiveSignature as Signature, B256, U256}; use alloy_provider::Provider; +use alloy_rpc_types::Authorization; use alloy_signer::{ k256::{elliptic_curve::sec1::ToEncodedPoint, SecretKey}, Signer, diff --git a/crates/cast/src/lib.rs b/crates/cast/src/lib.rs index 70447311c719e..7ad227e0c8ab9 100644 --- a/crates/cast/src/lib.rs +++ b/crates/cast/src/lib.rs @@ -34,6 +34,7 @@ use foundry_common::{ }; use foundry_compilers::flatten::Flattener; use foundry_config::Chain; +use foundry_evm_core::ic::decode_instructions; use futures::{future::Either, FutureExt, StreamExt}; use rayon::prelude::*; use std::{ @@ -46,7 +47,6 @@ use std::{ time::Duration, }; use tokio::signal::ctrl_c; -use utils::decode_instructions; use foundry_common::abi::encode_function_args_packed; pub use foundry_evm::*; diff --git a/crates/cheatcodes/Cargo.toml b/crates/cheatcodes/Cargo.toml index 49611dcca071c..c5a784c338dec 100644 --- a/crates/cheatcodes/Cargo.toml +++ b/crates/cheatcodes/Cargo.toml @@ -25,6 +25,7 @@ foundry-wallets.workspace = true forge-script-sequence.workspace = true alloy-dyn-abi.workspace = true +alloy-evm.workspace = true alloy-json-abi.workspace = true alloy-primitives.workspace = true alloy-genesis.workspace = true diff --git a/crates/cheatcodes/src/error.rs b/crates/cheatcodes/src/error.rs index b77c889d59ab7..4bb9f1395bf2b 100644 --- a/crates/cheatcodes/src/error.rs +++ b/crates/cheatcodes/src/error.rs @@ -8,7 +8,7 @@ use foundry_config::UnresolvedEnvVarError; use foundry_evm_core::backend::{BackendError, DatabaseError}; use foundry_wallets::error::WalletSignerError; use k256::ecdsa::signature::Error as SignatureError; -use revm::primitives::EVMError; +use revm::context_interface::result::EVMError; use std::{borrow::Cow, fmt}; /// Cheatcode result type. diff --git a/crates/cheatcodes/src/evm.rs b/crates/cheatcodes/src/evm.rs index 543b6189784e9..456c4337e4bff 100644 --- a/crates/cheatcodes/src/evm.rs +++ b/crates/cheatcodes/src/evm.rs @@ -1,7 +1,7 @@ //! Implementations of [`Evm`](spec::Group::Evm) cheatcodes. use crate::{ - inspector::{InnerEcx, RecordDebugStepInfo}, + inspector::{Ecx, RecordDebugStepInfo}, BroadcastableTransaction, Cheatcode, Cheatcodes, CheatcodesExecutor, CheatsCtxt, Error, Result, Vm::*, }; @@ -14,11 +14,17 @@ use foundry_common::fs::{read_json_file, write_json_file}; use foundry_evm_core::{ backend::{DatabaseExt, RevertStateSnapshotAction}, constants::{CALLER, CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, TEST_CONTRACT_ADDRESS}, + ContextExt, }; use foundry_evm_traces::StackSnapshotType; use itertools::Itertools; use rand::Rng; -use revm::primitives::{Account, Bytecode, SpecId, KECCAK_EMPTY}; +use revm::{ + bytecode::Bytecode, + context::{Block, JournalTr}, + primitives::{hardfork::SpecId, KECCAK_EMPTY}, + state::Account, +}; use std::{ collections::{btree_map::Entry, BTreeMap}, fmt::Display, @@ -74,7 +80,7 @@ pub struct GasRecord { /// The total gas used in the gas snapshot. pub gas_used: u64, /// Depth at which the gas snapshot was taken. - pub depth: u64, + pub depth: usize, } /// Records `deal` cheatcodes @@ -178,8 +184,8 @@ impl Cheatcode for loadCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target, slot } = *self; ensure_not_precompile!(&target, ccx); - ccx.ecx.load_account(target)?; - let mut val = ccx.ecx.sload(target, slot.into())?; + ccx.ecx.journaled_state.load_account(target)?; + let mut val = ccx.ecx.journaled_state.sload(target, slot.into())?; if val.is_cold && val.data.is_zero() { if ccx.state.has_arbitrary_storage(&target) { @@ -229,9 +235,8 @@ impl Cheatcode for loadAllocsCall { }; // Then, load the allocs into the database. - ccx.ecx - .db - .load_allocs(&allocs, &mut ccx.ecx.journaled_state) + let (db, journal, _) = ccx.ecx.as_db_env_and_journal(); + db.load_allocs(&allocs, journal) .map(|()| Vec::default()) .map_err(|e| fmt_err!("failed to load allocs: {e}")) } @@ -241,14 +246,12 @@ impl Cheatcode for cloneAccountCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { source, target } = self; - let account = ccx.ecx.journaled_state.load_account(*source, &mut ccx.ecx.db)?; - ccx.ecx.db.clone_account( - &genesis_account(account.data), - target, - &mut ccx.ecx.journaled_state, - )?; + let (db, journal, _) = ccx.ecx.as_db_env_and_journal(); + let account = journal.load_account(db, *source)?; + let genesis = &genesis_account(account.data); + db.clone_account(genesis, target, journal)?; // Cloned account should persist in forked envs. - ccx.ecx.db.add_persistent_account(*target); + ccx.ecx.journaled_state.database.add_persistent_account(*target); Ok(Default::default()) } } @@ -363,7 +366,7 @@ impl Cheatcode for chainIdCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newChainId } = self; ensure!(*newChainId <= U256::from(u64::MAX), "chain ID must be less than 2^64 - 1"); - ccx.ecx.env.cfg.chain_id = newChainId.to(); + ccx.ecx.cfg.chain_id = newChainId.to(); Ok(Default::default()) } } @@ -371,7 +374,7 @@ impl Cheatcode for chainIdCall { impl Cheatcode for coinbaseCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newCoinbase } = self; - ccx.ecx.env.block.coinbase = *newCoinbase; + ccx.ecx.block.beneficiary = *newCoinbase; Ok(Default::default()) } } @@ -380,11 +383,11 @@ impl Cheatcode for difficultyCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newDifficulty } = self; ensure!( - ccx.ecx.spec_id() < SpecId::MERGE, + ccx.ecx.cfg.spec < SpecId::MERGE, "`difficulty` is not supported after the Paris hard fork, use `prevrandao` instead; \ see EIP-4399: https://eips.ethereum.org/EIPS/eip-4399" ); - ccx.ecx.env.block.difficulty = *newDifficulty; + ccx.ecx.block.difficulty = *newDifficulty; Ok(Default::default()) } } @@ -392,7 +395,8 @@ impl Cheatcode for difficultyCall { impl Cheatcode for feeCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newBasefee } = self; - ccx.ecx.env.block.basefee = *newBasefee; + ensure!(*newBasefee <= U256::from(u64::MAX), "base fee must be less than 2^64 - 1"); + ccx.ecx.block.basefee = newBasefee.saturating_to(); Ok(Default::default()) } } @@ -401,11 +405,11 @@ impl Cheatcode for prevrandao_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newPrevrandao } = self; ensure!( - ccx.ecx.spec_id() >= SpecId::MERGE, + ccx.ecx.cfg.spec >= SpecId::MERGE, "`prevrandao` is not supported before the Paris hard fork, use `difficulty` instead; \ see EIP-4399: https://eips.ethereum.org/EIPS/eip-4399" ); - ccx.ecx.env.block.prevrandao = Some(*newPrevrandao); + ccx.ecx.block.prevrandao = Some(*newPrevrandao); Ok(Default::default()) } } @@ -414,11 +418,11 @@ impl Cheatcode for prevrandao_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newPrevrandao } = self; ensure!( - ccx.ecx.spec_id() >= SpecId::MERGE, + ccx.ecx.cfg.spec >= SpecId::MERGE, "`prevrandao` is not supported before the Paris hard fork, use `difficulty` instead; \ see EIP-4399: https://eips.ethereum.org/EIPS/eip-4399" ); - ccx.ecx.env.block.prevrandao = Some((*newPrevrandao).into()); + ccx.ecx.block.prevrandao = Some((*newPrevrandao).into()); Ok(Default::default()) } } @@ -427,11 +431,11 @@ impl Cheatcode for blobhashesCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { hashes } = self; ensure!( - ccx.ecx.spec_id() >= SpecId::CANCUN, + ccx.ecx.cfg.spec >= SpecId::CANCUN, "`blobhashes` is not supported before the Cancun hard fork; \ see EIP-4844: https://eips.ethereum.org/EIPS/eip-4844" ); - ccx.ecx.env.tx.blob_hashes.clone_from(hashes); + ccx.ecx.tx.blob_hashes.clone_from(hashes); Ok(Default::default()) } } @@ -440,18 +444,19 @@ impl Cheatcode for getBlobhashesCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; ensure!( - ccx.ecx.spec_id() >= SpecId::CANCUN, + ccx.ecx.cfg.spec >= SpecId::CANCUN, "`getBlobhashes` is not supported before the Cancun hard fork; \ see EIP-4844: https://eips.ethereum.org/EIPS/eip-4844" ); - Ok(ccx.ecx.env.tx.blob_hashes.clone().abi_encode()) + Ok(ccx.ecx.tx.blob_hashes.clone().abi_encode()) } } impl Cheatcode for rollCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newHeight } = self; - ccx.ecx.env.block.number = *newHeight; + ensure!(*newHeight <= U256::from(u64::MAX), "block height must be less than 2^64 - 1"); + ccx.ecx.block.number = newHeight.saturating_to(); Ok(Default::default()) } } @@ -459,14 +464,15 @@ impl Cheatcode for rollCall { impl Cheatcode for getBlockNumberCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; - Ok(ccx.ecx.env.block.number.abi_encode()) + Ok(ccx.ecx.block.number.abi_encode()) } } impl Cheatcode for txGasPriceCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newGasPrice } = self; - ccx.ecx.env.tx.gas_price = *newGasPrice; + ensure!(*newGasPrice <= U256::from(u64::MAX), "gas price must be less than 2^64 - 1"); + ccx.ecx.tx.gas_price = newGasPrice.saturating_to(); Ok(Default::default()) } } @@ -474,7 +480,8 @@ impl Cheatcode for txGasPriceCall { impl Cheatcode for warpCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newTimestamp } = self; - ccx.ecx.env.block.timestamp = *newTimestamp; + ensure!(*newTimestamp <= U256::from(u64::MAX), "timestamp must be less than 2^64 - 1"); + ccx.ecx.block.timestamp = newTimestamp.saturating_to(); Ok(Default::default()) } } @@ -482,7 +489,7 @@ impl Cheatcode for warpCall { impl Cheatcode for getBlockTimestampCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; - Ok(ccx.ecx.env.block.timestamp.abi_encode()) + Ok(ccx.ecx.block.timestamp.abi_encode()) } } @@ -490,14 +497,12 @@ impl Cheatcode for blobBaseFeeCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { newBlobBaseFee } = self; ensure!( - ccx.ecx.spec_id() >= SpecId::CANCUN, + ccx.ecx.cfg.spec >= SpecId::CANCUN, "`blobBaseFee` is not supported before the Cancun hard fork; \ see EIP-4844: https://eips.ethereum.org/EIPS/eip-4844" ); - ccx.ecx.env.block.set_blob_excess_gas_and_price( - (*newBlobBaseFee).to(), - ccx.ecx.spec_id() >= SpecId::PRAGUE, - ); + let is_prague = ccx.ecx.cfg.spec >= SpecId::PRAGUE; + ccx.ecx.block.set_blob_excess_gas_and_price((*newBlobBaseFee).to(), is_prague); Ok(Default::default()) } } @@ -505,7 +510,7 @@ impl Cheatcode for blobBaseFeeCall { impl Cheatcode for getBlobBaseFeeCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; - Ok(ccx.ecx.env.block.get_blob_excess_gas().unwrap_or(0).abi_encode()) + Ok(ccx.ecx.block.blob_excess_gas().unwrap_or(0).abi_encode()) } } @@ -524,7 +529,7 @@ impl Cheatcode for etchCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { target, newRuntimeBytecode } = self; ensure_not_precompile!(target, ccx); - ccx.ecx.load_account(*target)?; + ccx.ecx.journaled_state.load_account(*target)?; let bytecode = Bytecode::new_raw_checked(Bytes::copy_from_slice(newRuntimeBytecode)) .map_err(|e| fmt_err!("failed to create bytecode: {e}"))?; ccx.ecx.journaled_state.set_code(*target, bytecode); @@ -578,7 +583,7 @@ impl Cheatcode for storeCall { ensure_not_precompile!(&target, ccx); // ensure the account is touched let _ = journaled_account(ccx.ecx, target)?; - ccx.ecx.sstore(target, slot.into(), value.into())?; + ccx.ecx.journaled_state.sstore(target, slot.into(), value.into())?; Ok(Default::default()) } } @@ -639,7 +644,7 @@ impl Cheatcode for coolSlotCall { impl Cheatcode for readCallersCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; - read_callers(ccx.state, &ccx.ecx.env.tx.caller, ccx.ecx.journaled_state.depth()) + read_callers(ccx.state, &ccx.ecx.tx.caller, ccx.ecx.journaled_state.depth()) } } @@ -831,16 +836,17 @@ impl Cheatcode for broadcastRawTransactionCall { let tx = TxEnvelope::decode(&mut self.data.as_ref()) .map_err(|err| fmt_err!("failed to decode RLP-encoded transaction: {err}"))?; - ccx.ecx.db.transact_from_tx( + let (db, journal, env) = ccx.ecx.as_db_env_and_journal(); + db.transact_from_tx( &tx.clone().into(), - (*ccx.ecx.env).clone(), - &mut ccx.ecx.journaled_state, + env.to_owned(), + journal, &mut *executor.get_inspector(ccx.state), )?; if ccx.state.broadcast.is_some() { ccx.state.broadcastable_transactions.push_back(BroadcastableTransaction { - rpc: ccx.db.active_fork_url(), + rpc: ccx.ecx.journaled_state.database.active_fork_url(), transaction: tx.try_into()?, }); } @@ -852,12 +858,13 @@ impl Cheatcode for broadcastRawTransactionCall { impl Cheatcode for setBlockhashCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { blockNumber, blockHash } = *self; + ensure!(blockNumber <= U256::from(u64::MAX), "blockNumber must be less than 2^64 - 1"); ensure!( - blockNumber <= ccx.ecx.env.block.number, + blockNumber <= U256::from(ccx.ecx.block.number), "block number must be less than or equal to the current block number" ); - ccx.ecx.db.set_blockhash(blockNumber, blockHash); + ccx.ecx.journaled_state.database.set_blockhash(blockNumber, blockHash); Ok(Default::default()) } @@ -930,23 +937,22 @@ impl Cheatcode for stopAndReturnDebugTraceRecordingCall { } pub(super) fn get_nonce(ccx: &mut CheatsCtxt, address: &Address) -> Result { - let account = ccx.ecx.journaled_state.load_account(*address, &mut ccx.ecx.db)?; + let account = ccx.ecx.journaled_state.load_account(*address)?; Ok(account.info.nonce.abi_encode()) } fn inner_snapshot_state(ccx: &mut CheatsCtxt) -> Result { - Ok(ccx.ecx.db.snapshot_state(&ccx.ecx.journaled_state, &ccx.ecx.env).abi_encode()) + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + Ok(db.snapshot_state(journal, &mut env).abi_encode()) } fn inner_revert_to_state(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { - let result = if let Some(journaled_state) = ccx.ecx.db.revert_state( - snapshot_id, - &ccx.ecx.journaled_state, - &mut ccx.ecx.env, - RevertStateSnapshotAction::RevertKeep, - ) { + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + let result = if let Some(journaled_state) = + db.revert_state(snapshot_id, &*journal, &mut env, RevertStateSnapshotAction::RevertKeep) + { // we reset the evm's journaled_state to the state of the snapshot previous state - ccx.ecx.journaled_state = journaled_state; + ccx.ecx.journaled_state.inner = journaled_state; true } else { false @@ -955,14 +961,13 @@ fn inner_revert_to_state(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { } fn inner_revert_to_state_and_delete(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { - let result = if let Some(journaled_state) = ccx.ecx.db.revert_state( - snapshot_id, - &ccx.ecx.journaled_state, - &mut ccx.ecx.env, - RevertStateSnapshotAction::RevertRemove, - ) { + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + + let result = if let Some(journaled_state) = + db.revert_state(snapshot_id, &*journal, &mut env, RevertStateSnapshotAction::RevertRemove) + { // we reset the evm's journaled_state to the state of the snapshot previous state - ccx.ecx.journaled_state = journaled_state; + ccx.ecx.journaled_state.inner = journaled_state; true } else { false @@ -971,12 +976,12 @@ fn inner_revert_to_state_and_delete(ccx: &mut CheatsCtxt, snapshot_id: U256) -> } fn inner_delete_state_snapshot(ccx: &mut CheatsCtxt, snapshot_id: U256) -> Result { - let result = ccx.ecx.db.delete_state_snapshot(snapshot_id); + let result = ccx.ecx.journaled_state.database.delete_state_snapshot(snapshot_id); Ok(result.abi_encode()) } fn inner_delete_state_snapshots(ccx: &mut CheatsCtxt) -> Result { - ccx.ecx.db.delete_state_snapshots(); + ccx.ecx.journaled_state.database.delete_state_snapshots(); Ok(Default::default()) } @@ -1119,7 +1124,7 @@ fn derive_snapshot_name( /// - If no caller modification is active: /// - caller_mode will be equal to [CallerMode::None], /// - `msg.sender` and `tx.origin` will be equal to the default sender address. -fn read_callers(state: &Cheatcodes, default_sender: &Address, call_depth: u64) -> Result { +fn read_callers(state: &Cheatcodes, default_sender: &Address, call_depth: usize) -> Result { let mut mode = CallerMode::None; let mut new_caller = default_sender; let mut new_origin = default_sender; @@ -1144,11 +1149,11 @@ fn read_callers(state: &Cheatcodes, default_sender: &Address, call_depth: u64) - /// Ensures the `Account` is loaded and touched. pub(super) fn journaled_account<'a>( - ecx: InnerEcx<'a, '_, '_>, + ecx: Ecx<'a, '_, '_>, addr: Address, ) -> Result<&'a mut Account> { - ecx.load_account(addr)?; - ecx.journaled_state.touch(&addr); + ecx.journaled_state.load_account(addr)?; + ecx.journaled_state.touch(addr); Ok(ecx.journaled_state.state.get_mut(&addr).expect("account is loaded")) } diff --git a/crates/cheatcodes/src/evm/fork.rs b/crates/cheatcodes/src/evm/fork.rs index e78aa3be9f697..65a7a04d401cc 100644 --- a/crates/cheatcodes/src/evm/fork.rs +++ b/crates/cheatcodes/src/evm/fork.rs @@ -8,13 +8,14 @@ use alloy_provider::Provider; use alloy_rpc_types::Filter; use alloy_sol_types::SolValue; use foundry_common::provider::ProviderBuilder; -use foundry_evm_core::fork::CreateFork; +use foundry_evm_core::{fork::CreateFork, AsEnvMut, ContextExt}; impl Cheatcode for activeForkCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; ccx.ecx - .db + .journaled_state + .database .active_fork_id() .map(|id| id.abi_encode()) .ok_or_else(|| fmt_err!("no active fork")) @@ -67,12 +68,8 @@ impl Cheatcode for rollFork_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { blockNumber } = self; persist_caller(ccx); - ccx.ecx.db.roll_fork( - None, - (*blockNumber).to(), - &mut ccx.ecx.env, - &mut ccx.ecx.journaled_state, - )?; + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + db.roll_fork(None, (*blockNumber).to(), &mut env, journal)?; Ok(Default::default()) } } @@ -81,12 +78,8 @@ impl Cheatcode for rollFork_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { txHash } = self; persist_caller(ccx); - ccx.ecx.db.roll_fork_to_transaction( - None, - *txHash, - &mut ccx.ecx.env, - &mut ccx.ecx.journaled_state, - )?; + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + db.roll_fork_to_transaction(None, *txHash, &mut env, journal)?; Ok(Default::default()) } } @@ -95,12 +88,8 @@ impl Cheatcode for rollFork_2Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { forkId, blockNumber } = self; persist_caller(ccx); - ccx.ecx.db.roll_fork( - Some(*forkId), - (*blockNumber).to(), - &mut ccx.ecx.env, - &mut ccx.ecx.journaled_state, - )?; + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + db.roll_fork(Some(*forkId), (*blockNumber).to(), &mut env, journal)?; Ok(Default::default()) } } @@ -109,12 +98,8 @@ impl Cheatcode for rollFork_3Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { forkId, txHash } = self; persist_caller(ccx); - ccx.ecx.db.roll_fork_to_transaction( - Some(*forkId), - *txHash, - &mut ccx.ecx.env, - &mut ccx.ecx.journaled_state, - )?; + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + db.roll_fork_to_transaction(Some(*forkId), *txHash, &mut env, journal)?; Ok(Default::default()) } } @@ -124,8 +109,8 @@ impl Cheatcode for selectForkCall { let Self { forkId } = self; persist_caller(ccx); check_broadcast(ccx.state)?; - - ccx.ecx.db.select_fork(*forkId, &mut ccx.ecx.env, &mut ccx.ecx.journaled_state)?; + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + db.select_fork(*forkId, &mut env, journal)?; Ok(Default::default()) } } @@ -147,7 +132,7 @@ impl Cheatcode for transact_1Call { impl Cheatcode for allowCheatcodesCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - ccx.ecx.db.allow_cheatcode_access(*account); + ccx.ecx.journaled_state.database.allow_cheatcode_access(*account); Ok(Default::default()) } } @@ -155,7 +140,7 @@ impl Cheatcode for allowCheatcodesCall { impl Cheatcode for makePersistent_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - ccx.ecx.db.add_persistent_account(*account); + ccx.ecx.journaled_state.database.add_persistent_account(*account); Ok(Default::default()) } } @@ -163,8 +148,8 @@ impl Cheatcode for makePersistent_0Call { impl Cheatcode for makePersistent_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account0, account1 } = self; - ccx.ecx.db.add_persistent_account(*account0); - ccx.ecx.db.add_persistent_account(*account1); + ccx.ecx.journaled_state.database.add_persistent_account(*account0); + ccx.ecx.journaled_state.database.add_persistent_account(*account1); Ok(Default::default()) } } @@ -172,9 +157,9 @@ impl Cheatcode for makePersistent_1Call { impl Cheatcode for makePersistent_2Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account0, account1, account2 } = self; - ccx.ecx.db.add_persistent_account(*account0); - ccx.ecx.db.add_persistent_account(*account1); - ccx.ecx.db.add_persistent_account(*account2); + ccx.ecx.journaled_state.database.add_persistent_account(*account0); + ccx.ecx.journaled_state.database.add_persistent_account(*account1); + ccx.ecx.journaled_state.database.add_persistent_account(*account2); Ok(Default::default()) } } @@ -183,7 +168,7 @@ impl Cheatcode for makePersistent_3Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { accounts } = self; for account in accounts { - ccx.ecx.db.add_persistent_account(*account); + ccx.ecx.journaled_state.database.add_persistent_account(*account); } Ok(Default::default()) } @@ -192,7 +177,7 @@ impl Cheatcode for makePersistent_3Call { impl Cheatcode for revokePersistent_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - ccx.ecx.db.remove_persistent_account(account); + ccx.ecx.journaled_state.database.remove_persistent_account(account); Ok(Default::default()) } } @@ -201,7 +186,7 @@ impl Cheatcode for revokePersistent_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { accounts } = self; for account in accounts { - ccx.ecx.db.remove_persistent_account(account); + ccx.ecx.journaled_state.database.remove_persistent_account(account); } Ok(Default::default()) } @@ -210,15 +195,19 @@ impl Cheatcode for revokePersistent_1Call { impl Cheatcode for isPersistentCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { account } = self; - Ok(ccx.ecx.db.is_persistent(account).abi_encode()) + Ok(ccx.ecx.journaled_state.database.is_persistent(account).abi_encode()) } } impl Cheatcode for rpc_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { method, params } = self; - let url = - ccx.ecx.db.active_fork_url().ok_or_else(|| fmt_err!("no active fork URL found"))?; + let url = ccx + .ecx + .journaled_state + .database + .active_fork_url() + .ok_or_else(|| fmt_err!("no active fork URL found"))?; rpc_call(&url, method, params) } } @@ -243,8 +232,12 @@ impl Cheatcode for eth_getLogsCall { bail!("topics array must contain at most 4 elements") } - let url = - ccx.ecx.db.active_fork_url().ok_or_else(|| fmt_err!("no active fork URL found"))?; + let url = ccx + .ecx + .journaled_state + .database + .active_fork_url() + .ok_or_else(|| fmt_err!("no active fork URL found"))?; let provider = ProviderBuilder::new(&url).build()?; let mut filter = Filter::new().address(*target).from_block(from_block).to_block(to_block); for (i, &topic) in topics.iter().enumerate() { @@ -278,14 +271,15 @@ fn create_select_fork(ccx: &mut CheatsCtxt, url_or_alias: &str, block: Option) -> Result { let fork = create_fork_request(ccx, url_or_alias, block)?; - let id = ccx.ecx.db.create_fork(fork)?; + let id = ccx.ecx.journaled_state.database.create_fork(fork)?; Ok(id.abi_encode()) } @@ -298,12 +292,8 @@ fn create_select_fork_at_transaction( check_broadcast(ccx.state)?; let fork = create_fork_request(ccx, url_or_alias, None)?; - let id = ccx.ecx.db.create_select_fork_at_transaction( - fork, - &mut ccx.ecx.env, - &mut ccx.ecx.journaled_state, - *transaction, - )?; + let (db, journal, mut env) = ccx.ecx.as_db_env_and_journal(); + let id = db.create_select_fork_at_transaction(fork, &mut env, journal, *transaction)?; Ok(id.abi_encode()) } @@ -314,7 +304,7 @@ fn create_fork_at_transaction( transaction: &B256, ) -> Result { let fork = create_fork_request(ccx, url_or_alias, None)?; - let id = ccx.ecx.db.create_fork_at_transaction(fork, *transaction)?; + let id = ccx.ecx.journaled_state.database.create_fork_at_transaction(fork, *transaction)?; Ok(id.abi_encode()) } @@ -339,7 +329,7 @@ fn create_fork_request( enable_caching: !ccx.state.config.no_storage_caching && ccx.state.config.rpc_storage_caching.enable_for_endpoint(&url), url, - env: (*ccx.ecx.env).clone(), + env: ccx.ecx.as_env_mut().to_owned(), evm_opts, }; Ok(fork) @@ -359,11 +349,12 @@ fn transact( transaction: B256, fork_id: Option, ) -> Result { - ccx.ecx.db.transact( + let (db, journal, env) = ccx.ecx.as_db_env_and_journal(); + db.transact( fork_id, transaction, - (*ccx.ecx.env).clone(), - &mut ccx.ecx.journaled_state, + env.to_owned(), + journal, &mut *executor.get_inspector(ccx.state), )?; Ok(Default::default()) @@ -374,7 +365,7 @@ fn transact( // Applies to create, select and roll forks actions. // https://github.com/foundry-rs/foundry/issues/8004 fn persist_caller(ccx: &mut CheatsCtxt) { - ccx.ecx.db.add_persistent_account(ccx.caller); + ccx.ecx.journaled_state.database.add_persistent_account(ccx.caller); } /// Performs an Ethereum JSON-RPC request to the given endpoint. diff --git a/crates/cheatcodes/src/evm/mapping.rs b/crates/cheatcodes/src/evm/mapping.rs index e8525908e847a..569d0e0cb7724 100644 --- a/crates/cheatcodes/src/evm/mapping.rs +++ b/crates/cheatcodes/src/evm/mapping.rs @@ -5,7 +5,13 @@ use alloy_primitives::{ Address, B256, U256, }; use alloy_sol_types::SolValue; -use revm::interpreter::{opcode, Interpreter}; +use revm::{ + bytecode::opcode, + interpreter::{ + interpreter_types::{Jumps, MemoryTr}, + Interpreter, + }, +}; /// Recorded mapping slots. #[derive(Clone, Debug, Default)] @@ -117,22 +123,21 @@ fn slot_child<'a>( #[cold] pub(crate) fn step(mapping_slots: &mut AddressHashMap, interpreter: &Interpreter) { - match interpreter.current_opcode() { + match interpreter.bytecode.opcode() { opcode::KECCAK256 => { if interpreter.stack.peek(1) == Ok(U256::from(0x40)) { - let address = interpreter.contract.target_address; + let address = interpreter.input.target_address; let offset = interpreter.stack.peek(0).expect("stack size > 1").saturating_to(); - let data = interpreter.shared_memory.slice(offset, 0x40); + let data = interpreter.memory.slice_len(offset, 0x40); let low = B256::from_slice(&data[..0x20]); let high = B256::from_slice(&data[0x20..]); - let result = keccak256(data); + let result = keccak256(&*data); mapping_slots.entry(address).or_default().seen_sha3.insert(result, (low, high)); } } opcode::SSTORE => { - if let Some(mapping_slots) = mapping_slots.get_mut(&interpreter.contract.target_address) - { + if let Some(mapping_slots) = mapping_slots.get_mut(&interpreter.input.target_address) { if let Ok(slot) = interpreter.stack.peek(0) { mapping_slots.insert(slot.into()); } diff --git a/crates/cheatcodes/src/evm/mock.rs b/crates/cheatcodes/src/evm/mock.rs index fcfea7a9ce87c..dc2c2137ba524 100644 --- a/crates/cheatcodes/src/evm/mock.rs +++ b/crates/cheatcodes/src/evm/mock.rs @@ -1,6 +1,6 @@ -use crate::{inspector::InnerEcx, Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*}; +use crate::{Cheatcode, Cheatcodes, CheatsCtxt, Result, Vm::*}; use alloy_primitives::{Address, Bytes, U256}; -use revm::{interpreter::InstructionResult, primitives::Bytecode}; +use revm::{bytecode::Bytecode, context::JournalTr, interpreter::InstructionResult}; use std::{cmp::Ordering, collections::VecDeque}; /// Mocked call data. @@ -49,7 +49,7 @@ impl Cheatcode for clearMockedCallsCall { impl Cheatcode for mockCall_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, returnData } = self; - let _ = make_acc_non_empty(callee, ccx.ecx)?; + let _ = make_acc_non_empty(callee, ccx)?; mock_call(ccx.state, callee, data, None, returnData, InstructionResult::Return); Ok(Default::default()) @@ -59,7 +59,7 @@ impl Cheatcode for mockCall_0Call { impl Cheatcode for mockCall_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, msgValue, data, returnData } = self; - ccx.ecx.load_account(*callee)?; + ccx.ecx.journaled_state.load_account(*callee)?; mock_call(ccx.state, callee, data, Some(msgValue), returnData, InstructionResult::Return); Ok(Default::default()) } @@ -68,7 +68,7 @@ impl Cheatcode for mockCall_1Call { impl Cheatcode for mockCall_2Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, returnData } = self; - let _ = make_acc_non_empty(callee, ccx.ecx)?; + let _ = make_acc_non_empty(callee, ccx)?; mock_call( ccx.state, @@ -85,7 +85,7 @@ impl Cheatcode for mockCall_2Call { impl Cheatcode for mockCall_3Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, msgValue, data, returnData } = self; - ccx.ecx.load_account(*callee)?; + ccx.ecx.journaled_state.load_account(*callee)?; mock_call( ccx.state, callee, @@ -101,7 +101,7 @@ impl Cheatcode for mockCall_3Call { impl Cheatcode for mockCalls_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, returnData } = self; - let _ = make_acc_non_empty(callee, ccx.ecx)?; + let _ = make_acc_non_empty(callee, ccx)?; mock_calls(ccx.state, callee, data, None, returnData, InstructionResult::Return); Ok(Default::default()) @@ -111,7 +111,7 @@ impl Cheatcode for mockCalls_0Call { impl Cheatcode for mockCalls_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, msgValue, data, returnData } = self; - ccx.ecx.load_account(*callee)?; + ccx.ecx.journaled_state.load_account(*callee)?; mock_calls(ccx.state, callee, data, Some(msgValue), returnData, InstructionResult::Return); Ok(Default::default()) } @@ -120,7 +120,7 @@ impl Cheatcode for mockCalls_1Call { impl Cheatcode for mockCallRevert_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, revertData } = self; - let _ = make_acc_non_empty(callee, ccx.ecx)?; + let _ = make_acc_non_empty(callee, ccx)?; mock_call(ccx.state, callee, data, None, revertData, InstructionResult::Revert); Ok(Default::default()) @@ -130,7 +130,7 @@ impl Cheatcode for mockCallRevert_0Call { impl Cheatcode for mockCallRevert_1Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, msgValue, data, revertData } = self; - let _ = make_acc_non_empty(callee, ccx.ecx)?; + let _ = make_acc_non_empty(callee, ccx)?; mock_call(ccx.state, callee, data, Some(msgValue), revertData, InstructionResult::Revert); Ok(Default::default()) @@ -140,7 +140,7 @@ impl Cheatcode for mockCallRevert_1Call { impl Cheatcode for mockCallRevert_2Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, data, revertData } = self; - let _ = make_acc_non_empty(callee, ccx.ecx)?; + let _ = make_acc_non_empty(callee, ccx)?; mock_call( ccx.state, @@ -157,7 +157,7 @@ impl Cheatcode for mockCallRevert_2Call { impl Cheatcode for mockCallRevert_3Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { callee, msgValue, data, revertData } = self; - let _ = make_acc_non_empty(callee, ccx.ecx)?; + let _ = make_acc_non_empty(callee, ccx)?; mock_call( ccx.state, @@ -210,8 +210,8 @@ fn mock_calls( // Etches a single byte onto the account if it is empty to circumvent the `extcodesize` // check Solidity might perform. -fn make_acc_non_empty(callee: &Address, ecx: InnerEcx) -> Result { - let acc = ecx.load_account(*callee)?; +fn make_acc_non_empty(callee: &Address, ecx: &mut CheatsCtxt) -> Result { + let acc = ecx.journaled_state.load_account(*callee)?; let empty_bytecode = acc.info.code.as_ref().is_none_or(Bytecode::is_empty); if empty_bytecode { diff --git a/crates/cheatcodes/src/evm/prank.rs b/crates/cheatcodes/src/evm/prank.rs index 195760e702f46..96ab6cb9df925 100644 --- a/crates/cheatcodes/src/evm/prank.rs +++ b/crates/cheatcodes/src/evm/prank.rs @@ -1,5 +1,6 @@ use crate::{Cheatcode, CheatsCtxt, Result, Vm::*}; use alloy_primitives::Address; +use revm::{context::JournalTr, interpreter::Host}; /// Prank information. #[derive(Clone, Copy, Debug, Default)] @@ -13,7 +14,7 @@ pub struct Prank { /// The address to assign to `tx.origin` pub new_origin: Option
, /// The depth at which the prank was called - pub depth: u64, + pub depth: usize, /// Whether the prank stops by itself after the next call pub single_call: bool, /// Whether the prank should be applied to delegate call @@ -29,7 +30,7 @@ impl Prank { prank_origin: Address, new_caller: Address, new_origin: Option
, - depth: u64, + depth: usize, single_call: bool, delegate_call: bool, ) -> Self { @@ -129,8 +130,11 @@ fn prank( ) -> Result { // Ensure that code exists at `msg.sender` if delegate calling. if delegate_call { - let code = ccx.code(*new_caller)?; - ensure!(!code.is_empty(), "cannot `prank` delegate call from an EOA"); + let code = ccx + .load_account_code(*new_caller) + .ok_or_else(|| eyre::eyre!("cannot `prank` delegate call from an EOA"))?; + + ensure!(!code.data.is_empty(), "cannot `prank` delegate call from an EOA"); } let depth = ccx.ecx.journaled_state.depth(); @@ -147,7 +151,7 @@ fn prank( let prank = Prank::new( ccx.caller, - ccx.ecx.env.tx.caller, + ccx.ecx.tx.caller, *new_caller, new_origin.copied(), depth, diff --git a/crates/cheatcodes/src/evm/record_debug_step.rs b/crates/cheatcodes/src/evm/record_debug_step.rs index 1b1756936652e..bc78c2425c414 100644 --- a/crates/cheatcodes/src/evm/record_debug_step.rs +++ b/crates/cheatcodes/src/evm/record_debug_step.rs @@ -1,7 +1,7 @@ use alloy_primitives::{Bytes, U256}; use foundry_evm_traces::CallTraceArena; -use revm::interpreter::{InstructionResult, OpCode}; +use revm::{bytecode::opcode::OpCode, interpreter::InstructionResult}; use foundry_evm_core::buffer::{get_buffer_accesses, BufferKind}; use revm_inspectors::tracing::types::{CallTraceStep, RecordedMemory, TraceMemberOrder}; diff --git a/crates/cheatcodes/src/fs.rs b/crates/cheatcodes/src/fs.rs index 940d5f6d8ef3c..f1985eb32bbc1 100644 --- a/crates/cheatcodes/src/fs.rs +++ b/crates/cheatcodes/src/fs.rs @@ -12,7 +12,7 @@ use dialoguer::{Input, Password}; use forge_script_sequence::{BroadcastReader, TransactionWithMetadata}; use foundry_common::fs; use foundry_config::fs_permissions::FsAccessKind; -use revm::interpreter::CreateInputs; +use revm::{context::CreateScheme, interpreter::CreateInputs}; use revm_inspectors::tracing::types::CallKind; use semver::Version; use std::{ @@ -97,7 +97,7 @@ impl Cheatcode for closeFileCall { let Self { path } = self; let path = state.config.ensure_path_allowed(path, FsAccessKind::Read)?; - state.context.opened_read_files.remove(&path); + state.test_context.opened_read_files.remove(&path); Ok(Default::default()) } @@ -167,7 +167,7 @@ impl Cheatcode for readLineCall { let path = state.config.ensure_path_allowed(path, FsAccessKind::Read)?; // Get reader for previously opened file to continue reading OR initialize new reader - let reader = match state.context.opened_read_files.entry(path.clone()) { + let reader = match state.test_context.opened_read_files.entry(path.clone()) { Entry::Occupied(entry) => entry.into_mut(), Entry::Vacant(entry) => entry.insert(BufReader::new(fs::open(path)?)), }; @@ -212,7 +212,7 @@ impl Cheatcode for removeFileCall { state.config.ensure_not_foundry_toml(&path)?; // also remove from the set if opened previously - state.context.opened_read_files.remove(&path); + state.test_context.opened_read_files.remove(&path); if state.fs_commit { fs::remove_file(&path)?; @@ -365,11 +365,8 @@ fn deploy_code( bytecode.extend_from_slice(args); } - let scheme = if let Some(salt) = salt { - revm::primitives::CreateScheme::Create2 { salt } - } else { - revm::primitives::CreateScheme::Create - }; + let scheme = + if let Some(salt) = salt { CreateScheme::Create2 { salt } } else { CreateScheme::Create }; let outcome = executor.exec_create( CreateInputs { @@ -753,7 +750,7 @@ impl Cheatcode for getBroadcasts_1Call { impl Cheatcode for getDeployment_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { contractName } = self; - let chain_id = ccx.ecx.env.cfg.chain_id; + let chain_id = ccx.ecx.cfg.chain_id; let latest_broadcast = latest_broadcast( contractName, diff --git a/crates/cheatcodes/src/inspector.rs b/crates/cheatcodes/src/inspector.rs index 4664f4da15d7c..e940300b43b25 100644 --- a/crates/cheatcodes/src/inspector.rs +++ b/crates/cheatcodes/src/inspector.rs @@ -22,6 +22,7 @@ use crate::{ Vm::{self, AccountAccess}, }; use alloy_consensus::BlobTransactionSidecar; +use alloy_evm::eth::EthEvmContext; use alloy_network::TransactionBuilder4844; use alloy_primitives::{ hex, @@ -38,7 +39,7 @@ use foundry_evm_core::{ abi::Vm::stopExpectSafeMemoryCall, backend::{DatabaseError, DatabaseExt, RevertDiagnostic}, constants::{CHEATCODE_ADDRESS, HARDHAT_CONSOLE_ADDRESS, MAGIC_ASSUME}, - utils::new_evm_with_existing_context, + evm::{new_evm_with_existing_context, FoundryEvm}, InspectorExt, }; use foundry_evm_traces::{TracingInspector, TracingInspectorConfig}; @@ -47,16 +48,20 @@ use itertools::Itertools; use proptest::test_runner::{RngAlgorithm, TestRng, TestRunner}; use rand::Rng; use revm::{ + self, + bytecode::{opcode as op, EOF_MAGIC_BYTES}, + context::{result::EVMError, BlockEnv, JournalTr}, + context_interface::{transaction::SignedAuthorization, CreateScheme}, + handler::FrameResult, interpreter::{ - opcode as op, CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, - EOFCreateInputs, EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterAction, + interpreter_types::{Jumps, LoopControl, MemoryTr}, + CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, EOFCreateInputs, + EOFCreateKind, FrameInput, Gas, Host, InstructionResult, Interpreter, InterpreterAction, InterpreterResult, }, - primitives::{ - BlockEnv, CreateScheme, EVMError, EvmStorageSlot, SignedAuthorization, SpecId, - EOF_MAGIC_BYTES, - }, - EvmContext, InnerEvmContext, Inspector, + primitives::hardfork::SpecId, + state::EvmStorageSlot, + Inspector, Journal, }; use serde_json::Value; use std::{ @@ -71,8 +76,7 @@ use std::{ mod utils; -pub type Ecx<'a, 'b, 'c> = &'a mut EvmContext<&'b mut (dyn DatabaseExt + 'c)>; -pub type InnerEcx<'a, 'b, 'c> = &'a mut InnerEvmContext<&'b mut (dyn DatabaseExt + 'c)>; +pub type Ecx<'a, 'b, 'c> = &'a mut EthEvmContext<&'b mut (dyn DatabaseExt + 'c)>; /// Helper trait for obtaining complete [revm::Inspector] instance from mutable reference to /// [Cheatcodes]. @@ -84,46 +88,36 @@ pub trait CheatcodesExecutor { /// [revm::Inspector]. fn get_inspector<'a>(&'a mut self, cheats: &'a mut Cheatcodes) -> Box; - /// Obtains [revm::Evm] instance and executes the given CREATE frame. + /// Obtains [FoundryEvm] instance and executes the given CREATE frame. fn exec_create( &mut self, inputs: CreateInputs, ccx: &mut CheatsCtxt, ) -> Result> { with_evm(self, ccx, |evm| { - evm.context.evm.inner.journaled_state.depth += 1; + evm.inner.data.ctx.journaled_state.depth += 1; // Handle EOF bytecode - let first_frame_or_result = if evm.handler.cfg.spec_id.is_enabled_in(SpecId::OSAKA) && + let frame = if evm.inner.data.ctx.cfg.spec.is_enabled_in(SpecId::OSAKA) && inputs.scheme == CreateScheme::Create && inputs.init_code.starts_with(&EOF_MAGIC_BYTES) { - evm.handler.execution().eofcreate( - &mut evm.context, - Box::new(EOFCreateInputs::new( - inputs.caller, - inputs.value, - inputs.gas_limit, - EOFCreateKind::Tx { initdata: inputs.init_code }, - )), - )? + FrameInput::EOFCreate(Box::new(EOFCreateInputs::new( + inputs.caller, + inputs.value, + inputs.gas_limit, + EOFCreateKind::Tx { initdata: inputs.init_code }, + ))) } else { - evm.handler.execution().create(&mut evm.context, Box::new(inputs))? - }; - - let mut result = match first_frame_or_result { - revm::FrameOrResult::Frame(first_frame) => evm.run_the_loop(first_frame)?, - revm::FrameOrResult::Result(result) => result, + FrameInput::Create(Box::new(inputs)) }; - evm.handler.execution().last_frame_return(&mut evm.context, &mut result)?; - - let outcome = match result { - revm::FrameResult::Call(_) => unreachable!(), - revm::FrameResult::Create(create) | revm::FrameResult::EOFCreate(create) => create, + let outcome = match evm.run_execution(frame)? { + FrameResult::Call(_) => unreachable!(), + FrameResult::Create(create) | FrameResult::EOFCreate(create) => create, }; - evm.context.evm.inner.journaled_state.depth -= 1; + evm.inner.data.ctx.journaled_state.depth -= 1; Ok(outcome) }) @@ -139,7 +133,7 @@ pub trait CheatcodesExecutor { } } -/// Constructs [revm::Evm] and runs a given closure with it. +/// Constructs [FoundryEvm] and runs a given closure with it. fn with_evm( executor: &mut E, ccx: &mut CheatsCtxt, @@ -148,32 +142,33 @@ fn with_evm( where E: CheatcodesExecutor + ?Sized, F: for<'a, 'b> FnOnce( - &mut revm::Evm<'_, &'b mut dyn InspectorExt, &'a mut dyn DatabaseExt>, + &mut FoundryEvm<'a, &'b mut dyn InspectorExt>, ) -> Result>, { let mut inspector = executor.get_inspector(ccx.state); let error = std::mem::replace(&mut ccx.ecx.error, Ok(())); - let l1_block_info = std::mem::take(&mut ccx.ecx.l1_block_info); - - let inner = revm::InnerEvmContext { - env: ccx.ecx.env.clone(), - journaled_state: std::mem::replace( - &mut ccx.ecx.journaled_state, - revm::JournaledState::new(Default::default(), Default::default()), - ), - db: &mut ccx.ecx.db as &mut dyn DatabaseExt, + + let ctx = EthEvmContext { + block: ccx.ecx.block.clone(), + cfg: ccx.ecx.cfg.clone(), + tx: ccx.ecx.tx.clone(), + journaled_state: Journal { + inner: ccx.ecx.journaled_state.inner.clone(), + database: &mut *ccx.ecx.journaled_state.database as &mut dyn DatabaseExt, + }, + chain: (), error, - l1_block_info, }; - let mut evm = new_evm_with_existing_context(inner, &mut *inspector); + let mut evm = new_evm_with_existing_context(ctx, &mut *inspector); let res = f(&mut evm)?; - ccx.ecx.journaled_state = evm.context.evm.inner.journaled_state; - ccx.ecx.env = evm.context.evm.inner.env; - ccx.ecx.l1_block_info = evm.context.evm.inner.l1_block_info; - ccx.ecx.error = evm.context.evm.inner.error; + ccx.ecx.journaled_state.inner = evm.inner.data.ctx.journaled_state.inner; + ccx.ecx.block = evm.inner.data.ctx.block; + ccx.ecx.tx = evm.inner.data.ctx.tx; + ccx.ecx.cfg = evm.inner.data.ctx.cfg; + ccx.ecx.error = evm.inner.data.ctx.error; Ok(res) } @@ -200,19 +195,19 @@ macro_rules! try_or_return { /// Contains additional, test specific resources that should be kept for the duration of the test #[derive(Debug, Default)] -pub struct Context { +pub struct TestContext { /// Buffered readers for files opened for reading (path => BufReader mapping) pub opened_read_files: HashMap>, } /// Every time we clone `Context`, we want it to be empty -impl Clone for Context { +impl Clone for TestContext { fn clone(&self) -> Self { Default::default() } } -impl Context { +impl TestContext { /// Clears the context. #[inline] pub fn clear(&mut self) { @@ -328,9 +323,9 @@ impl ArbitraryStorage { /// Saves arbitrary storage value for a given address: /// - store value in changed values cache. /// - update account's storage with given value. - pub fn save(&mut self, ecx: InnerEcx, address: Address, slot: U256, data: U256) { + pub fn save(&mut self, ecx: Ecx, address: Address, slot: U256, data: U256) { self.values.get_mut(&address).expect("missing arbitrary address entry").insert(slot, data); - if let Ok(mut account) = ecx.load_account(address) { + if let Ok(mut account) = ecx.journaled_state.load_account(address) { account.storage.insert(slot, EvmStorageSlot::new(data)); } } @@ -340,7 +335,7 @@ impl ArbitraryStorage { /// existing value. /// - if no value was yet generated for given slot, then save new value in cache and update both /// source and target storages. - pub fn copy(&mut self, ecx: InnerEcx, target: Address, slot: U256, new_value: U256) -> U256 { + pub fn copy(&mut self, ecx: Ecx, target: Address, slot: U256, new_value: U256) -> U256 { let source = self.copies.get(&target).expect("missing arbitrary copy target entry"); let storage_cache = self.values.get_mut(source).expect("missing arbitrary source storage"); let value = match storage_cache.get(&slot) { @@ -348,14 +343,14 @@ impl ArbitraryStorage { None => { storage_cache.insert(slot, new_value); // Update source storage with new value. - if let Ok(mut source_account) = ecx.load_account(*source) { + if let Ok(mut source_account) = ecx.journaled_state.load_account(*source) { source_account.storage.insert(slot, EvmStorageSlot::new(new_value)); } new_value } }; // Update target storage with new value. - if let Ok(mut target_account) = ecx.load_account(target) { + if let Ok(mut target_account) = ecx.journaled_state.load_account(target) { target_account.storage.insert(slot, EvmStorageSlot::new(value)); } value @@ -402,13 +397,13 @@ pub struct Cheatcodes { /// /// Used in the cheatcode handler to overwrite the gas price separately from the gas price /// in the execution environment. - pub gas_price: Option, + pub gas_price: Option, /// Address labels pub labels: AddressHashMap, /// Prank information, mapped to the call depth where pranks were added. - pub pranks: BTreeMap, + pub pranks: BTreeMap, /// Expected revert information pub expected_revert: Option, @@ -468,7 +463,7 @@ pub struct Cheatcodes { pub config: Arc, /// Test-scoped context holding data that needs to be reset every test run - pub context: Context, + pub test_context: TestContext, /// Whether to commit FS changes such as file creations, writes and deletes. /// Used to prevent duplicate changes file executing non-committing calls. @@ -554,7 +549,7 @@ impl Cheatcodes { broadcast: Default::default(), broadcastable_transactions: Default::default(), access_list: Default::default(), - context: Default::default(), + test_context: Default::default(), serialized_jsons: Default::default(), eth_deals: Default::default(), gas_metering: Default::default(), @@ -574,7 +569,7 @@ impl Cheatcodes { /// Returns the configured prank at given depth or the first prank configured at a lower depth. /// For example, if pranks configured for depth 1, 3 and 5, the prank for depth 4 is the one /// configured at depth 3. - pub fn get_prank(&self, depth: u64) -> Option<&Prank> { + pub fn get_prank(&self, depth: usize) -> Option<&Prank> { self.pranks.range(..=depth).last().map(|(_, prank)| prank) } @@ -612,17 +607,11 @@ impl Cheatcodes { // ensure the caller is allowed to execute cheatcodes, // but only if the backend is in forking mode - ecx.db.ensure_cheatcode_access_forking_mode(&caller)?; + ecx.journaled_state.database.ensure_cheatcode_access_forking_mode(&caller)?; apply_dispatch( &decoded, - &mut CheatsCtxt { - state: self, - ecx: &mut ecx.inner, - precompiles: &mut ecx.precompiles, - gas_limit: call.gas_limit, - caller, - }, + &mut CheatsCtxt { state: self, ecx, gas_limit: call.gas_limit, caller }, executor, ) } @@ -632,9 +621,11 @@ impl Cheatcodes { /// /// There may be cheatcodes in the constructor of the new contract, in order to allow them /// automatically we need to determine the new address. - fn allow_cheatcodes_on_create(&self, ecx: InnerEcx, caller: Address, created_address: Address) { - if ecx.journaled_state.depth <= 1 || ecx.db.has_cheatcode_access(&caller) { - ecx.db.allow_cheatcode_access(created_address); + fn allow_cheatcodes_on_create(&self, ecx: Ecx, caller: Address, created_address: Address) { + if ecx.journaled_state.depth <= 1 || + ecx.journaled_state.database.has_cheatcode_access(&caller) + { + ecx.journaled_state.database.allow_cheatcode_access(created_address); } } @@ -689,7 +680,6 @@ impl Cheatcodes { }); } - let ecx = &mut ecx.inner; let gas = Gas::new(input.gas_limit()); let curr_depth = ecx.journaled_state.depth(); @@ -699,14 +689,14 @@ impl Cheatcodes { let mut prank_applied = false; // At the target depth we set `msg.sender` - if ecx.journaled_state.depth() == prank.depth { + if curr_depth == prank.depth { input.set_caller(prank.new_caller); prank_applied = true; } // At the target depth, or deeper, we set `tx.origin` if let Some(new_origin) = prank.new_origin { - ecx.env.tx.caller = new_origin; + ecx.tx.caller = new_origin; prank_applied = true; } @@ -721,15 +711,13 @@ impl Cheatcodes { // Apply EIP-2930 access lists. if let Some(access_list) = &self.access_list { - ecx.env.tx.access_list = access_list.to_vec(); + ecx.tx.access_list = access_list.clone() } // Apply our broadcast if let Some(broadcast) = &self.broadcast { if curr_depth >= broadcast.depth && input.caller() == broadcast.original_caller { - if let Err(err) = - ecx.journaled_state.load_account(broadcast.new_origin, &mut ecx.db) - { + if let Err(err) = ecx.journaled_state.load_account(broadcast.new_origin) { return Some(CreateOutcome { result: InterpreterResult { result: InstructionResult::Revert, @@ -740,15 +728,15 @@ impl Cheatcodes { }); } - ecx.env.tx.caller = broadcast.new_origin; + ecx.tx.caller = broadcast.new_origin; if curr_depth == broadcast.depth { input.set_caller(broadcast.new_origin); - let is_fixed_gas_limit = check_if_fixed_gas_limit(ecx, input.gas_limit()); + let is_fixed_gas_limit = check_if_fixed_gas_limit(&ecx, input.gas_limit()); - let account = &ecx.journaled_state.state()[&broadcast.new_origin]; + let account = &ecx.journaled_state.inner.state()[&broadcast.new_origin]; self.broadcastable_transactions.push_back(BroadcastableTransaction { - rpc: ecx.db.active_fork_url(), + rpc: ecx.journaled_state.database.active_fork_url(), transaction: TransactionRequest { from: Some(broadcast.new_origin), to: None, @@ -773,8 +761,8 @@ impl Cheatcodes { if let Some(recorded_account_diffs_stack) = &mut self.recorded_account_diffs_stack { recorded_account_diffs_stack.push(vec![AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.db.active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.env.cfg.chain_id), + forkId: ecx.journaled_state.db().active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg.chain_id), }, accessor: input.caller(), account: address, @@ -787,7 +775,7 @@ impl Cheatcodes { reverted: false, deployedCode: Bytes::new(), // updated on (eof)create_end storageAccesses: vec![], // updated on (eof)create_end - depth: curr_depth, + depth: curr_depth as u64, }]); } @@ -799,16 +787,14 @@ impl Cheatcodes { &mut self, ecx: Ecx, call: Option<&CreateInputs>, - mut outcome: CreateOutcome, - ) -> CreateOutcome -where { - let ecx = &mut ecx.inner; + outcome: &mut CreateOutcome, + ) { let curr_depth = ecx.journaled_state.depth(); // Clean up pranks if let Some(prank) = &self.get_prank(curr_depth) { if curr_depth == prank.depth { - ecx.env.tx.caller = prank.prank_origin; + ecx.tx.caller = prank.prank_origin; // Clean single-call prank once we have returned to the original depth if prank.single_call { @@ -820,7 +806,7 @@ where { // Clean up broadcasts if let Some(broadcast) = &self.broadcast { if curr_depth == broadcast.depth { - ecx.env.tx.caller = broadcast.original_origin; + ecx.tx.caller = broadcast.original_origin; // Clean single-call broadcast once we have returned to the original depth if broadcast.single_call { @@ -853,12 +839,10 @@ where { outcome.result.result = InstructionResult::Return; outcome.result.output = retdata; outcome.address = address; - outcome } Err(err) => { outcome.result.result = InstructionResult::Revert; outcome.result.output = err.abi_encode().into(); - outcome } }; } @@ -887,15 +871,14 @@ where { // changes. Depending on what depth the cheat was called at, there // may not be any pending calls to update if execution has // percolated up to a higher depth. - if create_access.depth == ecx.journaled_state.depth() { + let depth = ecx.journaled_state.depth(); + if create_access.depth == depth as u64 { debug_assert_eq!( create_access.kind as u8, crate::Vm::AccountAccessKind::Create as u8 ); if let Some(address) = outcome.address { - if let Ok(created_acc) = - ecx.journaled_state.load_account(address, &mut ecx.db) - { + if let Ok(created_acc) = ecx.journaled_state.load_account(address) { create_access.newBalance = created_acc.info.balance; create_access.deployedCode = created_acc .info @@ -923,13 +906,13 @@ where { // Match the create against expected_creates if !self.expected_creates.is_empty() { if let (Some(address), Some(call)) = (outcome.address, call) { - if let Ok(created_acc) = ecx.journaled_state.load_account(address, &mut ecx.db) { + if let Ok(created_acc) = ecx.journaled_state.load_account(address) { let bytecode = created_acc.info.code.clone().unwrap_or_default().original_bytes(); if let Some((index, _)) = self.expected_creates.iter().find_position(|expected_create| { expected_create.deployer == call.caller && - expected_create.create_scheme.eq(call.scheme) && + expected_create.create_scheme.eq(call.scheme.into()) && expected_create.bytecode == bytecode }) { @@ -938,8 +921,6 @@ where { } } } - - outcome } pub fn call_with_executor( @@ -955,7 +936,7 @@ where { // decreasing sender nonce to ensure that it matches on-chain nonce once we start // broadcasting. if curr_depth == 0 { - let sender = ecx.env.tx.caller; + let sender = ecx.tx.caller; let account = match super::evm::journaled_account(ecx, sender) { Ok(account) => account, Err(err) => { @@ -996,8 +977,6 @@ where { }; } - let ecx = &mut ecx.inner; - if call.target_address == HARDHAT_CONSOLE_ADDRESS { return None; } @@ -1069,7 +1048,7 @@ where { call.target_address = prank.new_caller; call.caller = prank.new_caller; if let Some(new_origin) = prank.new_origin { - ecx.env.tx.caller = new_origin; + ecx.tx.caller = new_origin; } } } @@ -1085,7 +1064,7 @@ where { // At the target depth, or deeper, we set `tx.origin` if let Some(new_origin) = prank.new_origin { - ecx.env.tx.caller = new_origin; + ecx.tx.caller = new_origin; prank_applied = true; } @@ -1100,7 +1079,7 @@ where { // Apply EIP-2930 access lists. if let Some(access_list) = &self.access_list { - ecx.env.tx.access_list = access_list.to_vec(); + ecx.tx.access_list = access_list.clone() } // Apply our broadcast @@ -1113,7 +1092,7 @@ where { // At the target depth we set `msg.sender` & tx.origin. // We are simulating the caller as being an EOA, so *both* must be set to the // broadcast.origin. - ecx.env.tx.caller = broadcast.new_origin; + ecx.tx.caller = broadcast.new_origin; call.caller = broadcast.new_origin; // Add a `legacy` transaction to the VecDeque. We use a legacy transaction here @@ -1121,7 +1100,7 @@ where { // into 1559, in the cli package, relatively easily once we // know the target chain supports EIP-1559. if !call.is_static { - if let Err(err) = ecx.load_account(broadcast.new_origin) { + if let Err(err) = ecx.journaled_state.load_account(broadcast.new_origin) { return Some(CallOutcome { result: InterpreterResult { result: InstructionResult::Revert, @@ -1132,10 +1111,10 @@ where { }); } - let is_fixed_gas_limit = check_if_fixed_gas_limit(ecx, call.gas_limit); + let is_fixed_gas_limit = check_if_fixed_gas_limit(&ecx, call.gas_limit); let account = - ecx.journaled_state.state().get_mut(&broadcast.new_origin).unwrap(); + ecx.journaled_state.inner.state().get_mut(&broadcast.new_origin).unwrap(); let mut tx_req = TransactionRequest { from: Some(broadcast.new_origin), @@ -1143,7 +1122,7 @@ where { value: call.transfer_value(), input: TransactionInput::new(call.input.clone()), nonce: Some(account.info.nonce), - chain_id: Some(ecx.env.cfg.chain_id), + chain_id: Some(ecx.cfg.chain_id), gas: if is_fixed_gas_limit { Some(call.gas_limit) } else { None }, ..Default::default() }; @@ -1178,7 +1157,7 @@ where { } self.broadcastable_transactions.push_back(BroadcastableTransaction { - rpc: ecx.db.active_fork_url(), + rpc: ecx.journaled_state.database.active_fork_url(), transaction: tx_req.into(), }); debug!(target: "cheatcodes", tx=?self.broadcastable_transactions.back().unwrap(), "broadcastable call"); @@ -1210,7 +1189,7 @@ where { // nonce, a non-zero KECCAK_EMPTY codehash, or non-empty code let initialized; let old_balance; - if let Ok(acc) = ecx.load_account(call.target_address) { + if let Ok(acc) = ecx.journaled_state.load_account(call.target_address) { initialized = acc.info.exists(); old_balance = acc.info.balance; } else { @@ -1233,8 +1212,8 @@ where { // as "warm" if the call from which they were accessed is reverted recorded_account_diffs_stack.push(vec![AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.db.active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.env.cfg.chain_id), + forkId: ecx.journaled_state.db().active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg.chain_id), }, accessor: call.caller, account: call.bytecode_address, @@ -1247,7 +1226,11 @@ where { reverted: false, deployedCode: Bytes::new(), storageAccesses: vec![], // updated on step - depth: ecx.journaled_state.depth(), + depth: ecx + .journaled_state + .depth() + .try_into() + .expect("journaled state depth exceeds u64"), }]); } @@ -1312,21 +1295,21 @@ where { } } -impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { +impl Inspector> for Cheatcodes { #[inline] fn initialize_interp(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { // When the first interpreter is initialized we've circumvented the balance and gas checks, // so we apply our actual block data with the correct fees and all. if let Some(block) = self.block.take() { - ecx.env.block = block; + ecx.block = block; } if let Some(gas_price) = self.gas_price.take() { - ecx.env.tx.gas_price = gas_price; + ecx.tx.gas_price = gas_price; } // Record gas for current frame. if self.gas_metering.paused { - self.gas_metering.paused_frames.push(interpreter.gas); + self.gas_metering.paused_frames.push(interpreter.control.gas); } // `expectRevert`: track the max call depth during `expectRevert` @@ -1337,7 +1320,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { #[inline] fn step(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { - self.pc = interpreter.program_counter(); + self.pc = interpreter.bytecode.pc(); // `pauseGasMetering`: pause / resume interpreter gas. if self.gas_metering.paused { @@ -1361,7 +1344,10 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { // `expectSafeMemory`: check if the current opcode is allowed to interact with memory. if !self.allowed_mem_writes.is_empty() { - self.check_mem_opcodes(interpreter, ecx.journaled_state.depth()); + self.check_mem_opcodes( + interpreter, + ecx.journaled_state.depth().try_into().expect("journaled state depth exceeds u64"), + ); } // `startMappingRecording`: record SSTORE and KECCAK256. @@ -1391,9 +1377,9 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { } } - fn log(&mut self, interpreter: &mut Interpreter, _ecx: Ecx, log: &Log) { + fn log(&mut self, interpreter: &mut Interpreter, _ecx: Ecx, log: Log) { if !self.expected_emits.is_empty() { - expect::handle_expect_emit(self, log, interpreter); + expect::handle_expect_emit(self, &log, interpreter); } // `recordLogs` @@ -1410,8 +1396,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { Self::call_with_executor(self, ecx, inputs, &mut TransparentCheatcodesExecutor) } - fn call_end(&mut self, ecx: Ecx, call: &CallInputs, mut outcome: CallOutcome) -> CallOutcome { - let ecx = &mut ecx.inner; + fn call_end(&mut self, ecx: Ecx, call: &CallInputs, outcome: &mut CallOutcome) { let cheatcode_call = call.target_address == CHEATCODE_ADDRESS || call.target_address == HARDHAT_CONSOLE_ADDRESS; @@ -1423,7 +1408,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { let curr_depth = ecx.journaled_state.depth(); if let Some(prank) = &self.get_prank(curr_depth) { if curr_depth == prank.depth { - ecx.env.tx.caller = prank.prank_origin; + ecx.tx.caller = prank.prank_origin; // Clean single-call prank once we have returned to the original depth if prank.single_call { @@ -1434,8 +1419,8 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { // Clean up broadcast if let Some(broadcast) = &self.broadcast { - if ecx.journaled_state.depth() == broadcast.depth { - ecx.env.tx.caller = broadcast.original_origin; + if curr_depth == broadcast.depth { + ecx.tx.caller = broadcast.original_origin; // Clean single-call broadcast once we have returned to the original depth if broadcast.single_call { @@ -1452,8 +1437,10 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { if outcome.result.is_revert() && assume_no_revert.reverted_by.is_none() { assume_no_revert.reverted_by = Some(call.target_address); } + // allow multiple cheatcode calls at the same depth - if ecx.journaled_state.depth() <= assume_no_revert.depth && !cheatcode_call { + let curr_depth = ecx.journaled_state.depth(); + if curr_depth <= assume_no_revert.depth && !cheatcode_call { // Discard run if we're at the same depth as cheatcode, call reverted, and no // specific reason was supplied if outcome.result.is_revert() { @@ -1468,7 +1455,6 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { // to reject this run Ok(_) => { outcome.result.output = Error::from(MAGIC_ASSUME).abi_encode().into(); - outcome } // if result is Error, it was an unanticipated revert; should revert // normally @@ -1476,13 +1462,11 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { trace!(expected=?assume_no_revert, ?error, status=?outcome.result.result, "Expected revert mismatch"); outcome.result.result = InstructionResult::Revert; outcome.result.output = error.abi_encode().into(); - outcome } } } else { // Call didn't revert, reset `assume_no_revert` state. self.assume_no_revert = None; - return outcome; } } } @@ -1502,7 +1486,8 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { } } - if ecx.journaled_state.depth() <= expected_revert.depth { + let curr_depth = ecx.journaled_state.depth(); + if curr_depth <= expected_revert.depth { let needs_processing = match expected_revert.kind { ExpectedRevertKind::Default => !cheatcode_call, // `pending_processing` == true means that we're in the `call_end` hook for @@ -1527,7 +1512,6 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { trace!(expected=?expected_revert, ?error, status=?outcome.result.result, "Expected revert mismatch"); outcome.result.result = InstructionResult::Revert; outcome.result.output = error.abi_encode().into(); - outcome } Ok((_, retdata)) => { expected_revert.actual_count += 1; @@ -1536,7 +1520,6 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { } outcome.result.result = InstructionResult::Return; outcome.result.output = retdata; - outcome } }; } @@ -1554,7 +1537,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { // Exit early for calls to cheatcodes as other logic is not relevant for cheatcode // invocations if cheatcode_call { - return outcome; + return; } // Record the gas usage of the call, this allows the `lastCallGas` cheatcode to @@ -1591,8 +1574,9 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { // changes. Depending on the depth the cheat was // called at, there may not be any pending // calls to update if execution has percolated up to a higher depth. - if call_access.depth == ecx.journaled_state.depth() { - if let Ok(acc) = ecx.load_account(call.target_address) { + let curr_depth = ecx.journaled_state.depth(); + if call_access.depth == curr_depth as u64 { + if let Ok(acc) = ecx.journaled_state.load_account(call.target_address) { debug_assert!(access_is_call(call_access.kind)); call_access.newBalance = acc.info.balance; } @@ -1625,7 +1609,10 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { let should_check_emits = self .expected_emits .iter() - .any(|(expected, _)| expected.depth == ecx.journaled_state.depth()) && + .any(|(expected, _)| { + let curr_depth = ecx.journaled_state.depth(); + expected.depth == curr_depth + }) && // Ignore staticcalls !call.is_static; if should_check_emits { @@ -1661,7 +1648,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { { outcome.result.result = InstructionResult::Revert; outcome.result.output = "log != expected log".abi_encode().into(); - return outcome; + return; } if !expected_counts.is_empty() { @@ -1676,7 +1663,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { outcome.result.result = InstructionResult::Revert; outcome.result.output = Error::encode(msg); - return outcome; + return; } // All emits were found, we're good. @@ -1694,21 +1681,22 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { if outcome.result.is_revert() { if let Some(err) = diag { outcome.result.output = Error::encode(err.to_error_msg(&self.labels)); - return outcome; + return; } } // try to diagnose reverts in multi-fork mode where a call is made to an address that does // not exist - if let TxKind::Call(test_contract) = ecx.env.tx.transact_to { + if let TxKind::Call(test_contract) = ecx.tx.kind { // if a call to a different contract than the original test contract returned with // `Stop` we check if the contract actually exists on the active fork - if ecx.db.is_forked_mode() && + if ecx.journaled_state.db().is_forked_mode() && outcome.result.result == InstructionResult::Stop && call.target_address != test_contract { + let journaled_state = ecx.journaled_state.clone(); self.fork_revert_diagnostic = - ecx.db.diagnose_revert(call.target_address, &ecx.journaled_state); + ecx.journaled_state.db().diagnose_revert(call.target_address, &journaled_state); } } @@ -1718,7 +1706,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { // earlier error that happened first with unrelated information about // another error when using cheatcodes. if outcome.result.is_revert() { - return outcome; + return; } // If there's not a revert, we can continue on to run the last logic for expect* @@ -1768,7 +1756,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { outcome.result.result = InstructionResult::Revert; outcome.result.output = Error::encode(msg); - return outcome; + return; } } } @@ -1787,7 +1775,7 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { }; outcome.result.result = InstructionResult::Revert; outcome.result.output = Error::encode(msg); - return outcome; + return; } // Check for leftover expected creates @@ -1800,23 +1788,15 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { ); outcome.result.result = InstructionResult::Revert; outcome.result.output = Error::encode(msg); - return outcome; } } - - outcome } fn create(&mut self, ecx: Ecx, call: &mut CreateInputs) -> Option { self.create_common(ecx, call) } - fn create_end( - &mut self, - ecx: Ecx, - call: &CreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + fn create_end(&mut self, ecx: Ecx, call: &CreateInputs, outcome: &mut CreateOutcome) { self.create_end_common(ecx, Some(call), outcome) } @@ -1824,18 +1804,13 @@ impl Inspector<&mut dyn DatabaseExt> for Cheatcodes { self.create_common(ecx, call) } - fn eofcreate_end( - &mut self, - ecx: Ecx, - _call: &EOFCreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + fn eofcreate_end(&mut self, ecx: Ecx, _call: &EOFCreateInputs, outcome: &mut CreateOutcome) { self.create_end_common(ecx, None, outcome) } } impl InspectorExt for Cheatcodes { - fn should_use_create2_factory(&mut self, ecx: Ecx, inputs: &mut CreateInputs) -> bool { + fn should_use_create2_factory(&mut self, ecx: Ecx, inputs: &CreateInputs) -> bool { if let CreateScheme::Create2 { .. } = inputs.scheme { let depth = ecx.journaled_state.depth(); let target_depth = if let Some(prank) = &self.get_prank(depth) { @@ -1863,29 +1838,36 @@ impl Cheatcodes { fn meter_gas(&mut self, interpreter: &mut Interpreter) { if let Some(paused_gas) = self.gas_metering.paused_frames.last() { // Keep gas constant if paused. - interpreter.gas = *paused_gas; + // Make sure we record the memory changes so that memory expansion is not paused. + let memory = interpreter.control.gas.memory; + interpreter.control.gas = *paused_gas; + interpreter.control.gas.memory = memory; } else { // Record frame paused gas. - self.gas_metering.paused_frames.push(interpreter.gas); + self.gas_metering.paused_frames.push(interpreter.control.gas); } } #[cold] fn meter_gas_record(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { - if matches!(interpreter.instruction_result, InstructionResult::Continue) { + if matches!(interpreter.control.instruction_result, InstructionResult::Continue) { self.gas_metering.gas_records.iter_mut().for_each(|record| { - if ecx.journaled_state.depth() == record.depth { + let curr_depth = ecx.journaled_state.depth(); + if curr_depth == record.depth { // Skip the first opcode of the first call frame as it includes the gas cost of // creating the snapshot. if self.gas_metering.last_gas_used != 0 { - let gas_diff = - interpreter.gas.spent().saturating_sub(self.gas_metering.last_gas_used); + let gas_diff = interpreter + .control + .gas + .spent() + .saturating_sub(self.gas_metering.last_gas_used); record.gas_used = record.gas_used.saturating_add(gas_diff); } // Update `last_gas_used` to the current spent gas for the next iteration to // compare against. - self.gas_metering.last_gas_used = interpreter.gas.spent(); + self.gas_metering.last_gas_used = interpreter.control.gas.spent(); } }); } @@ -1894,27 +1876,27 @@ impl Cheatcodes { #[cold] fn meter_gas_end(&mut self, interpreter: &mut Interpreter) { // Remove recorded gas if we exit frame. - if will_exit(interpreter.instruction_result) { + if will_exit(interpreter.control.instruction_result) { self.gas_metering.paused_frames.pop(); } } #[cold] fn meter_gas_reset(&mut self, interpreter: &mut Interpreter) { - interpreter.gas = Gas::new(interpreter.gas().limit()); + interpreter.control.gas = Gas::new(interpreter.control.gas().limit()); self.gas_metering.reset = false; } #[cold] fn meter_gas_check(&mut self, interpreter: &mut Interpreter) { - if will_exit(interpreter.instruction_result) { + if will_exit(interpreter.control.instruction_result) { // Reset gas if spent is less than refunded. // This can happen if gas was paused / resumed or reset. // https://github.com/foundry-rs/foundry/issues/4370 - if interpreter.gas.spent() < - u64::try_from(interpreter.gas.refunded()).unwrap_or_default() + if interpreter.control.gas.spent() < + u64::try_from(interpreter.control.gas.refunded()).unwrap_or_default() { - interpreter.gas = Gas::new(interpreter.gas.limit()); + interpreter.control.gas = Gas::new(interpreter.control.gas.limit()); } } } @@ -1928,13 +1910,13 @@ impl Cheatcodes { /// - generates arbitrary value and saves it in target address storage. #[cold] fn arbitrary_storage_end(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { - let (key, target_address) = if interpreter.current_opcode() == op::SLOAD { - (try_or_return!(interpreter.stack().peek(0)), interpreter.contract().target_address) + let (key, target_address) = if interpreter.bytecode.opcode() == op::SLOAD { + (try_or_return!(interpreter.stack.peek(0)), interpreter.input.target_address) } else { return }; - let Ok(value) = ecx.sload(target_address, key) else { + let Some(value) = ecx.sload(target_address, key) else { return; }; @@ -1944,7 +1926,7 @@ impl Cheatcodes { if self.has_arbitrary_storage(&target_address) { let arbitrary_value = self.rng().gen(); self.arbitrary_storage.as_mut().unwrap().save( - &mut ecx.inner, + ecx, target_address, key, arbitrary_value, @@ -1952,7 +1934,7 @@ impl Cheatcodes { } else if self.is_arbitrary_storage_copy(&target_address) { let arbitrary_value = self.rng().gen(); self.arbitrary_storage.as_mut().unwrap().copy( - &mut ecx.inner, + ecx, target_address, key, arbitrary_value, @@ -1965,14 +1947,14 @@ impl Cheatcodes { #[cold] fn record_accesses(&mut self, interpreter: &mut Interpreter) { let access = &mut self.accesses; - match interpreter.current_opcode() { + match interpreter.bytecode.opcode() { op::SLOAD => { - let key = try_or_return!(interpreter.stack().peek(0)); - access.record_read(interpreter.contract().target_address, key); + let key = try_or_return!(interpreter.stack.peek(0)); + access.record_read(interpreter.input.target_address, key); } op::SSTORE => { - let key = try_or_return!(interpreter.stack().peek(0)); - access.record_write(interpreter.contract().target_address, key); + let key = try_or_return!(interpreter.stack.peek(0)); + access.record_write(interpreter.input.target_address, key); } _ => {} } @@ -1981,32 +1963,33 @@ impl Cheatcodes { #[cold] fn record_state_diffs(&mut self, interpreter: &mut Interpreter, ecx: Ecx) { let Some(account_accesses) = &mut self.recorded_account_diffs_stack else { return }; - match interpreter.current_opcode() { + match interpreter.bytecode.opcode() { op::SELFDESTRUCT => { // Ensure that we're not selfdestructing a context recording was initiated on let Some(last) = account_accesses.last_mut() else { return }; // get previous balance and initialized status of the target account - let target = try_or_return!(interpreter.stack().peek(0)); + let target = try_or_return!(interpreter.stack.peek(0)); let target = Address::from_word(B256::from(target)); let (initialized, old_balance) = ecx + .journaled_state .load_account(target) .map(|account| (account.info.exists(), account.info.balance)) .unwrap_or_default(); // load balance of this account let value = ecx - .balance(interpreter.contract().target_address) + .balance(interpreter.input.target_address) .map(|b| b.data) .unwrap_or(U256::ZERO); // register access for the target account last.push(crate::Vm::AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.db.active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.env.cfg.chain_id), + forkId: ecx.journaled_state.database.active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg.chain_id), }, - accessor: interpreter.contract().target_address, + accessor: interpreter.input.target_address, account: target, kind: crate::Vm::AccountAccessKind::SelfDestruct, initialized, @@ -2017,46 +2000,55 @@ impl Cheatcodes { reverted: false, deployedCode: Bytes::new(), storageAccesses: vec![], - depth: ecx.journaled_state.depth(), + depth: ecx + .journaled_state + .depth() + .try_into() + .expect("journaled state depth exceeds u64"), }); } op::SLOAD => { let Some(last) = account_accesses.last_mut() else { return }; - let key = try_or_return!(interpreter.stack().peek(0)); - let address = interpreter.contract().target_address; + let key = try_or_return!(interpreter.stack.peek(0)); + let address = interpreter.input.target_address; // Try to include present value for informational purposes, otherwise assume // it's not set (zero value) let mut present_value = U256::ZERO; // Try to load the account and the slot's present value - if ecx.load_account(address).is_ok() { - if let Ok(previous) = ecx.sload(address, key) { + if ecx.journaled_state.load_account(address).is_ok() { + if let Some(previous) = ecx.sload(address, key) { present_value = previous.data; } } let access = crate::Vm::StorageAccess { - account: interpreter.contract().target_address, + account: interpreter.input.target_address, slot: key.into(), isWrite: false, previousValue: present_value.into(), newValue: present_value.into(), reverted: false, }; - append_storage_access(last, access, ecx.journaled_state.depth()); + let curr_depth = ecx + .journaled_state + .depth() + .try_into() + .expect("journaled state depth exceeds u64"); + append_storage_access(last, access, curr_depth); } op::SSTORE => { let Some(last) = account_accesses.last_mut() else { return }; - let key = try_or_return!(interpreter.stack().peek(0)); - let value = try_or_return!(interpreter.stack().peek(1)); - let address = interpreter.contract().target_address; + let key = try_or_return!(interpreter.stack.peek(0)); + let value = try_or_return!(interpreter.stack.peek(1)); + let address = interpreter.input.target_address; // Try to load the account and the slot's previous value, otherwise, assume it's // not set (zero value) let mut previous_value = U256::ZERO; - if ecx.load_account(address).is_ok() { - if let Ok(previous) = ecx.sload(address, key) { + if ecx.journaled_state.load_account(address).is_ok() { + if let Some(previous) = ecx.sload(address, key) { previous_value = previous.data; } } @@ -2069,12 +2061,17 @@ impl Cheatcodes { newValue: value.into(), reverted: false, }; - append_storage_access(last, access, ecx.journaled_state.depth()); + let curr_depth = ecx + .journaled_state + .depth() + .try_into() + .expect("journaled state depth exceeds u64"); + append_storage_access(last, access, curr_depth); } // Record account accesses via the EXT family of opcodes op::EXTCODECOPY | op::EXTCODESIZE | op::EXTCODEHASH | op::BALANCE => { - let kind = match interpreter.current_opcode() { + let kind = match interpreter.bytecode.opcode() { op::EXTCODECOPY => crate::Vm::AccountAccessKind::Extcodecopy, op::EXTCODESIZE => crate::Vm::AccountAccessKind::Extcodesize, op::EXTCODEHASH => crate::Vm::AccountAccessKind::Extcodehash, @@ -2082,22 +2079,27 @@ impl Cheatcodes { _ => unreachable!(), }; let address = - Address::from_word(B256::from(try_or_return!(interpreter.stack().peek(0)))); + Address::from_word(B256::from(try_or_return!(interpreter.stack.peek(0)))); let initialized; let balance; - if let Ok(acc) = ecx.load_account(address) { + if let Ok(acc) = ecx.journaled_state.load_account(address) { initialized = acc.info.exists(); balance = acc.info.balance; } else { initialized = false; balance = U256::ZERO; } + let curr_depth = ecx + .journaled_state + .depth() + .try_into() + .expect("journaled state depth exceeds u64"); let account_access = crate::Vm::AccountAccess { chainInfo: crate::Vm::ChainInfo { - forkId: ecx.db.active_fork_id().unwrap_or_default(), - chainId: U256::from(ecx.env.cfg.chain_id), + forkId: ecx.journaled_state.database.active_fork_id().unwrap_or_default(), + chainId: U256::from(ecx.cfg.chain_id), }, - accessor: interpreter.contract().target_address, + accessor: interpreter.input.target_address, account: address, kind, initialized, @@ -2108,7 +2110,7 @@ impl Cheatcodes { reverted: false, deployedCode: Bytes::new(), storageAccesses: vec![], - depth: ecx.journaled_state.depth(), + depth: curr_depth, }; // Record the EXT* call as an account access at the current depth // (future storage accesses will be recorded in a new "Resume" context) @@ -2142,14 +2144,14 @@ impl Cheatcodes { // size of the memory write is implicit, so these cases are hard-coded. macro_rules! mem_opcode_match { ($(($opcode:ident, $offset_depth:expr, $size_depth:expr, $writes:expr)),* $(,)?) => { - match interpreter.current_opcode() { + match interpreter.bytecode.opcode() { //////////////////////////////////////////////////////////////// // OPERATIONS THAT CAN EXPAND/MUTATE MEMORY BY WRITING // //////////////////////////////////////////////////////////////// op::MSTORE => { // The offset of the mstore operation is at the top of the stack. - let offset = try_or_return!(interpreter.stack().peek(0)).saturating_to::(); + let offset = try_or_return!(interpreter.stack.peek(0)).saturating_to::(); // If none of the allowed ranges contain [offset, offset + 32), memory has been // unexpectedly mutated. @@ -2160,7 +2162,7 @@ impl Cheatcodes { // `stopExpectSafeMemory`, this is allowed. It will do so at the current free memory // pointer, which could have been updated to the exclusive upper bound during // execution. - let value = try_or_return!(interpreter.stack().peek(1)).to_be_bytes::<32>(); + let value = try_or_return!(interpreter.stack.peek(1)).to_be_bytes::<32>(); if value[..SELECTOR_LEN] == stopExpectSafeMemoryCall::SELECTOR { return } @@ -2171,7 +2173,7 @@ impl Cheatcodes { } op::MSTORE8 => { // The offset of the mstore8 operation is at the top of the stack. - let offset = try_or_return!(interpreter.stack().peek(0)).saturating_to::(); + let offset = try_or_return!(interpreter.stack.peek(0)).saturating_to::(); // If none of the allowed ranges contain the offset, memory has been // unexpectedly mutated. @@ -2187,12 +2189,12 @@ impl Cheatcodes { op::MLOAD => { // The offset of the mload operation is at the top of the stack - let offset = try_or_return!(interpreter.stack().peek(0)).saturating_to::(); + let offset = try_or_return!(interpreter.stack.peek(0)).saturating_to::(); // If the offset being loaded is >= than the memory size, the // memory is being expanded. If none of the allowed ranges contain // [offset, offset + 32), memory has been unexpectedly mutated. - if offset >= interpreter.shared_memory.len() as u64 && !ranges.iter().any(|range| { + if offset >= interpreter.memory.size() as u64 && !ranges.iter().any(|range| { range.contains(&offset) && range.contains(&(offset + 31)) }) { disallowed_mem_write(offset, 32, interpreter, ranges); @@ -2206,10 +2208,10 @@ impl Cheatcodes { op::CALL => { // The destination offset of the operation is the fifth element on the stack. - let dest_offset = try_or_return!(interpreter.stack().peek(5)).saturating_to::(); + let dest_offset = try_or_return!(interpreter.stack.peek(5)).saturating_to::(); // The size of the data that will be copied is the sixth element on the stack. - let size = try_or_return!(interpreter.stack().peek(6)).saturating_to::(); + let size = try_or_return!(interpreter.stack.peek(6)).saturating_to::(); // If none of the allowed ranges contain [dest_offset, dest_offset + size), // memory outside of the expected ranges has been touched. If the opcode @@ -2225,11 +2227,11 @@ impl Cheatcodes { // SPECIAL CASE: When a call to `stopExpectSafeMemory` is performed, this is allowed. // It allocated calldata at the current free memory pointer, and will attempt to read // from this memory region to perform the call. - let to = Address::from_word(try_or_return!(interpreter.stack().peek(1)).to_be_bytes::<32>().into()); + let to = Address::from_word(try_or_return!(interpreter.stack.peek(1)).to_be_bytes::<32>().into()); if to == CHEATCODE_ADDRESS { - let args_offset = try_or_return!(interpreter.stack().peek(3)).saturating_to::(); - let args_size = try_or_return!(interpreter.stack().peek(4)).saturating_to::(); - let memory_word = interpreter.shared_memory.slice(args_offset, args_size); + let args_offset = try_or_return!(interpreter.stack.peek(3)).saturating_to::(); + let args_size = try_or_return!(interpreter.stack.peek(4)).saturating_to::(); + let memory_word = interpreter.memory.slice_len(args_offset, args_size); if memory_word[..SELECTOR_LEN] == stopExpectSafeMemoryCall::SELECTOR { return } @@ -2242,10 +2244,10 @@ impl Cheatcodes { $(op::$opcode => { // The destination offset of the operation. - let dest_offset = try_or_return!(interpreter.stack().peek($offset_depth)).saturating_to::(); + let dest_offset = try_or_return!(interpreter.stack.peek($offset_depth)).saturating_to::(); // The size of the data that will be copied. - let size = try_or_return!(interpreter.stack().peek($size_depth)).saturating_to::(); + let size = try_or_return!(interpreter.stack.peek($size_depth)).saturating_to::(); // If none of the allowed ranges contain [dest_offset, dest_offset + size), // memory outside of the expected ranges has been touched. If the opcode @@ -2255,7 +2257,7 @@ impl Cheatcodes { range.contains(&(dest_offset + size.saturating_sub(1))) }) && ($writes || [dest_offset, (dest_offset + size).saturating_sub(1)].into_iter().any(|offset| { - offset >= interpreter.shared_memory.len() as u64 + offset >= interpreter.memory.size() as u64 }) ); @@ -2314,11 +2316,11 @@ fn disallowed_mem_write( ranges.iter().map(|r| format!("(0x{:02X}, 0x{:02X}]", r.start, r.end)).join(" U ") ); - interpreter.instruction_result = InstructionResult::Revert; - interpreter.next_action = InterpreterAction::Return { + interpreter.control.instruction_result = InstructionResult::Revert; + interpreter.control.next_action = InterpreterAction::Return { result: InterpreterResult { output: Error::encode(revert_string), - gas: interpreter.gas, + gas: interpreter.control.gas, result: InstructionResult::Revert, }, }; @@ -2326,13 +2328,13 @@ fn disallowed_mem_write( // Determines if the gas limit on a given call was manually set in the script and should therefore // not be overwritten by later estimations -fn check_if_fixed_gas_limit(ecx: InnerEcx, call_gas_limit: u64) -> bool { +fn check_if_fixed_gas_limit(ecx: &Ecx, call_gas_limit: u64) -> bool { // If the gas limit was not set in the source code it is set to the estimated gas left at the // time of the call, which should be rather close to configured gas limit. // TODO: Find a way to reliably make this determination. // For example by generating it in the compilation or EVM simulation process - U256::from(ecx.env.tx.gas_limit) > ecx.env.block.gas_limit && - U256::from(call_gas_limit) <= ecx.env.block.gas_limit + ecx.tx.gas_limit > ecx.block.gas_limit && + call_gas_limit <= ecx.block.gas_limit // Transfers in forge scripts seem to be estimated at 2300 by revm leading to "Intrinsic // gas too low" failure when simulated on chain && call_gas_limit > 2300 diff --git a/crates/cheatcodes/src/inspector/utils.rs b/crates/cheatcodes/src/inspector/utils.rs index a0d7820aa3e27..bd71b2b18622f 100644 --- a/crates/cheatcodes/src/inspector/utils.rs +++ b/crates/cheatcodes/src/inspector/utils.rs @@ -1,4 +1,4 @@ -use super::InnerEcx; +use super::Ecx; use crate::inspector::Cheatcodes; use alloy_primitives::{Address, Bytes, U256}; use revm::interpreter::{CreateInputs, CreateScheme, EOFCreateInputs, EOFCreateKind}; @@ -12,7 +12,7 @@ pub(crate) trait CommonCreateInput { fn scheme(&self) -> Option; fn set_caller(&mut self, caller: Address); fn log_debug(&self, cheatcode: &mut Cheatcodes, scheme: &CreateScheme); - fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: InnerEcx) -> Address; + fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: Ecx) -> Address; fn computed_created_address(&self) -> Option
; } @@ -42,7 +42,7 @@ impl CommonCreateInput for &mut CreateInputs { }; debug!(target: "cheatcodes", tx=?cheatcode.broadcastable_transactions.back().unwrap(), "broadcastable {kind}"); } - fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: InnerEcx) -> Address { + fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: Ecx) -> Address { let old_nonce = ecx .journaled_state .state @@ -83,7 +83,7 @@ impl CommonCreateInput for &mut EOFCreateInputs { fn log_debug(&self, cheatcode: &mut Cheatcodes, _scheme: &CreateScheme) { debug!(target: "cheatcodes", tx=?cheatcode.broadcastable_transactions.back().unwrap(), "broadcastable eofcreate"); } - fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: InnerEcx) -> Address { + fn allow_cheatcodes(&self, cheatcodes: &mut Cheatcodes, ecx: Ecx) -> Address { let created_address = <&mut EOFCreateInputs as CommonCreateInput>::computed_created_address(self) .unwrap_or_default(); diff --git a/crates/cheatcodes/src/lib.rs b/crates/cheatcodes/src/lib.rs index 732f55d7e2533..ca45a937b0b63 100644 --- a/crates/cheatcodes/src/lib.rs +++ b/crates/cheatcodes/src/lib.rs @@ -15,15 +15,15 @@ pub extern crate foundry_cheatcodes_spec as spec; #[macro_use] extern crate tracing; +use alloy_evm::eth::EthEvmContext; use alloy_primitives::Address; use foundry_evm_core::backend::DatabaseExt; -use revm::{ContextPrecompiles, InnerEvmContext}; use spec::Status; pub use config::CheatsConfig; pub use error::{Error, ErrorKind, Result}; pub use inspector::{ - BroadcastableTransaction, BroadcastableTransactions, Cheatcodes, CheatcodesExecutor, Context, + BroadcastableTransaction, BroadcastableTransactions, Cheatcodes, CheatcodesExecutor, }; pub use spec::{CheatcodeDef, Vm}; pub use Vm::ForgeContext; @@ -138,9 +138,7 @@ pub struct CheatsCtxt<'cheats, 'evm, 'db, 'db2> { /// The cheatcodes inspector state. pub(crate) state: &'cheats mut Cheatcodes, /// The EVM data. - pub(crate) ecx: &'evm mut InnerEvmContext<&'db mut (dyn DatabaseExt + 'db2)>, - /// The precompiles context. - pub(crate) precompiles: &'evm mut ContextPrecompiles<&'db mut (dyn DatabaseExt + 'db2)>, + pub(crate) ecx: &'evm mut EthEvmContext<&'db mut (dyn DatabaseExt + 'db2)>, /// The original `msg.sender`. pub(crate) caller: Address, /// Gas limit of the current cheatcode call. @@ -148,7 +146,7 @@ pub struct CheatsCtxt<'cheats, 'evm, 'db, 'db2> { } impl<'db, 'db2> std::ops::Deref for CheatsCtxt<'_, '_, 'db, 'db2> { - type Target = InnerEvmContext<&'db mut (dyn DatabaseExt + 'db2)>; + type Target = EthEvmContext<&'db mut (dyn DatabaseExt + 'db2)>; #[inline(always)] fn deref(&self) -> &Self::Target { @@ -166,6 +164,6 @@ impl std::ops::DerefMut for CheatsCtxt<'_, '_, '_, '_> { impl CheatsCtxt<'_, '_, '_, '_> { #[inline] pub(crate) fn is_precompile(&self, address: &Address) -> bool { - self.precompiles.contains(address) + self.ecx.journaled_state.inner.precompiles.contains(address) } } diff --git a/crates/cheatcodes/src/script.rs b/crates/cheatcodes/src/script.rs index 2b3d6fc8efc24..ce27b79253cd3 100644 --- a/crates/cheatcodes/src/script.rs +++ b/crates/cheatcodes/src/script.rs @@ -9,7 +9,12 @@ use alloy_signer_local::PrivateKeySigner; use alloy_sol_types::SolValue; use foundry_wallets::{multi_wallet::MultiWallet, WalletSigner}; use parking_lot::Mutex; -use revm::primitives::{Bytecode, SignedAuthorization, SpecId, KECCAK_EMPTY}; +use revm::{ + bytecode::Bytecode, + context::JournalTr, + context_interface::transaction::SignedAuthorization, + primitives::{hardfork::SpecId, KECCAK_EMPTY}, +}; use std::sync::Arc; impl Cheatcode for broadcast_0Call { @@ -98,7 +103,7 @@ fn attach_delegation( let SignedDelegation { v, r, s, nonce, implementation } = delegation; // Set chain id to 0 if universal deployment is preferred. // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7702.md#protection-from-malleability-cross-chain - let chain_id = if cross_chain { U256::from(0) } else { U256::from(ccx.ecx.env.cfg.chain_id) }; + let chain_id = if cross_chain { U256::from(0) } else { U256::from(ccx.ecx.cfg.chain_id) }; let auth = Authorization { address: *implementation, nonce: *nonce, chain_id }; let signed_auth = SignedAuthorization::new_unchecked( @@ -126,12 +131,11 @@ fn sign_delegation( let nonce = if let Some(nonce) = nonce { nonce } else { - let authority_acc = - ccx.ecx.journaled_state.load_account(signer.address(), &mut ccx.ecx.db)?; + let authority_acc = ccx.ecx.journaled_state.load_account(signer.address())?; // If we don't have a nonce then use next auth account nonce. authority_acc.data.info.nonce + 1 }; - let chain_id = if cross_chain { U256::from(0) } else { U256::from(ccx.ecx.env.cfg.chain_id) }; + let chain_id = if cross_chain { U256::from(0) } else { U256::from(ccx.ecx.cfg.chain_id) }; let auth = Authorization { address: implementation, nonce, chain_id }; let sig = signer.sign_hash_sync(&auth.signature_hash())?; @@ -153,8 +157,7 @@ fn sign_delegation( fn write_delegation(ccx: &mut CheatsCtxt, auth: SignedAuthorization) -> Result<()> { let authority = auth.recover_authority().map_err(|e| format!("{e}"))?; - let authority_acc = ccx.ecx.journaled_state.load_account(authority, &mut ccx.ecx.db)?; - + let authority_acc = ccx.ecx.journaled_state.load_account(authority)?; if authority_acc.data.info.nonce + 1 != auth.nonce { return Err("invalid nonce".into()); } @@ -174,7 +177,7 @@ impl Cheatcode for attachBlobCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { blob } = self; ensure!( - ccx.ecx.spec_id() >= SpecId::CANCUN, + ccx.ecx.cfg.spec >= SpecId::CANCUN, "`attachBlob` is not supported before the Cancun hard fork; \ see EIP-4844: https://eips.ethereum.org/EIPS/eip-4844" ); @@ -233,7 +236,7 @@ pub struct Broadcast { /// Original `tx.origin` pub original_origin: Address, /// Depth of the broadcast - pub depth: u64, + pub depth: usize, /// Whether the prank stops by itself after the next call pub single_call: bool, } @@ -326,9 +329,9 @@ fn broadcast(ccx: &mut CheatsCtxt, new_origin: Option<&Address>, single_call: bo } let broadcast = Broadcast { - new_origin: new_origin.unwrap_or(ccx.ecx.env.tx.caller), + new_origin: new_origin.unwrap_or(ccx.ecx.tx.caller), original_caller: ccx.caller, - original_origin: ccx.ecx.env.tx.caller, + original_origin: ccx.ecx.tx.caller, depth, single_call, }; diff --git a/crates/cheatcodes/src/test.rs b/crates/cheatcodes/src/test.rs index 9a59430a9264c..bc36accccde12 100644 --- a/crates/cheatcodes/src/test.rs +++ b/crates/cheatcodes/src/test.rs @@ -78,7 +78,7 @@ impl Cheatcode for skip_1Call { if *skipTest { // Skip should not work if called deeper than at test level. // Since we're not returning the magic skip bytes, this will cause a test failure. - ensure!(ccx.ecx.journaled_state.depth() <= 1, "`skip` can only be used at test level"); + ensure!(ccx.ecx.journaled_state.depth <= 1, "`skip` can only be used at test level"); Err([MAGIC_SKIP, reason.as_bytes()].concat().into()) } else { Ok(Default::default()) diff --git a/crates/cheatcodes/src/test/assert.rs b/crates/cheatcodes/src/test/assert.rs index a61cc4b2a2ece..7bb433c88259f 100644 --- a/crates/cheatcodes/src/test/assert.rs +++ b/crates/cheatcodes/src/test/assert.rs @@ -6,6 +6,7 @@ use foundry_evm_core::{ constants::CHEATCODE_ADDRESS, }; use itertools::Itertools; +use revm::context::JournalTr; use std::fmt::{Debug, Display}; const EQ_REL_DELTA_RESOLUTION: U256 = U256::from_limbs([18, 0, 0, 0]); @@ -190,7 +191,11 @@ fn handle_assertion_result( Err(msg.into()) } else { executor.console_log(ccx, &msg); - ccx.ecx.sstore(CHEATCODE_ADDRESS, GLOBAL_FAIL_SLOT, U256::from(1))?; + ccx.ecx.journaled_state.sstore( + CHEATCODE_ADDRESS, + GLOBAL_FAIL_SLOT, + U256::from(1), + )?; Ok(Default::default()) } } diff --git a/crates/cheatcodes/src/test/assume.rs b/crates/cheatcodes/src/test/assume.rs index 74bd79e0964b6..6cdf3e621aece 100644 --- a/crates/cheatcodes/src/test/assume.rs +++ b/crates/cheatcodes/src/test/assume.rs @@ -9,7 +9,7 @@ use std::fmt::Debug; #[derive(Clone, Debug)] pub struct AssumeNoRevert { /// The call depth at which the cheatcode was added. - pub depth: u64, + pub depth: usize, /// Acceptable revert parameters for the next call, to be thrown out if they are encountered; /// reverts with parameters not specified here will count as normal reverts and not rejects /// towards the counter. @@ -56,7 +56,7 @@ impl Cheatcode for assumeCall { impl Cheatcode for assumeNoRevert_0Call { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { - assume_no_revert(ccx.state, ccx.ecx.journaled_state.depth(), vec![]) + assume_no_revert(ccx.state, ccx.ecx.journaled_state.depth, vec![]) } } @@ -65,7 +65,7 @@ impl Cheatcode for assumeNoRevert_1Call { let Self { potentialRevert } = self; assume_no_revert( ccx.state, - ccx.ecx.journaled_state.depth(), + ccx.ecx.journaled_state.depth, vec![AcceptableRevertParameters::from(potentialRevert)], ) } @@ -76,7 +76,7 @@ impl Cheatcode for assumeNoRevert_2Call { let Self { potentialReverts } = self; assume_no_revert( ccx.state, - ccx.ecx.journaled_state.depth(), + ccx.ecx.journaled_state.depth, potentialReverts.iter().map(AcceptableRevertParameters::from).collect(), ) } @@ -84,7 +84,7 @@ impl Cheatcode for assumeNoRevert_2Call { fn assume_no_revert( state: &mut Cheatcodes, - depth: u64, + depth: usize, parameters: Vec, ) -> Result { ensure!( diff --git a/crates/cheatcodes/src/test/expect.rs b/crates/cheatcodes/src/test/expect.rs index 9c3d79a3767bd..73748458c69c9 100644 --- a/crates/cheatcodes/src/test/expect.rs +++ b/crates/cheatcodes/src/test/expect.rs @@ -8,7 +8,10 @@ use alloy_primitives::{ map::{hash_map::Entry, AddressHashMap, HashMap}, Address, Bytes, LogData as RawLog, U256, }; -use revm::interpreter::{InstructionResult, Interpreter, InterpreterAction, InterpreterResult}; +use revm::{ + context::JournalTr, + interpreter::{InstructionResult, Interpreter, InterpreterAction, InterpreterResult}, +}; use super::revert_handlers::RevertParameters; /// Tracks the expected calls per address. @@ -66,7 +69,7 @@ pub struct ExpectedRevert { /// The expected data returned by the revert, None being any. pub reason: Option>, /// The depth at which the revert is expected. - pub depth: u64, + pub depth: usize, /// The type of expected revert. pub kind: ExpectedRevertKind, /// If true then only the first 4 bytes of expected data returned by the revert are checked. @@ -76,7 +79,7 @@ pub struct ExpectedRevert { /// Address that reverted the call. pub reverted_by: Option
, /// Max call depth reached during next call execution. - pub max_depth: u64, + pub max_depth: usize, /// Number of times this revert is expected. pub count: u64, /// Actual number of times this revert has been seen. @@ -86,7 +89,7 @@ pub struct ExpectedRevert { #[derive(Clone, Debug)] pub struct ExpectedEmit { /// The depth at which we expect this emit to have occurred - pub depth: u64, + pub depth: usize, /// The log we expect pub log: Option, /// The checks to perform: @@ -132,12 +135,20 @@ impl Display for CreateScheme { } } +impl From for CreateScheme { + fn from(scheme: revm::context_interface::CreateScheme) -> Self { + match scheme { + revm::context_interface::CreateScheme::Create => Self::Create, + revm::context_interface::CreateScheme::Create2 { .. } => Self::Create2, + } + } +} + impl CreateScheme { - pub fn eq(&self, create_scheme: revm::primitives::CreateScheme) -> bool { + pub fn eq(&self, create_scheme: Self) -> bool { matches!( (self, create_scheme), - (Self::Create, revm::primitives::CreateScheme::Create) | - (Self::Create2, revm::primitives::CreateScheme::Create2 { .. }) + (Self::Create, Self::Create) | (Self::Create2, Self::Create2 { .. }) ) } } @@ -623,14 +634,14 @@ impl Cheatcode for _expectCheatcodeRevert_2Call { impl Cheatcode for expectSafeMemoryCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { min, max } = *self; - expect_safe_memory(ccx.state, min, max, ccx.ecx.journaled_state.depth()) + expect_safe_memory(ccx.state, min, max, ccx.ecx.journaled_state.depth().try_into()?) } } impl Cheatcode for stopExpectSafeMemoryCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self {} = self; - ccx.state.allowed_mem_writes.remove(&ccx.ecx.journaled_state.depth()); + ccx.state.allowed_mem_writes.remove(&ccx.ecx.journaled_state.depth().try_into()?); Ok(Default::default()) } } @@ -638,7 +649,7 @@ impl Cheatcode for stopExpectSafeMemoryCall { impl Cheatcode for expectSafeMemoryCallCall { fn apply_stateful(&self, ccx: &mut CheatsCtxt) -> Result { let Self { min, max } = *self; - expect_safe_memory(ccx.state, min, max, ccx.ecx.journaled_state.depth() + 1) + expect_safe_memory(ccx.state, min, max, (ccx.ecx.journaled_state.depth() + 1).try_into()?) } } @@ -742,7 +753,7 @@ fn expect_call( fn expect_emit( state: &mut Cheatcodes, - depth: u64, + depth: usize, checks: [bool; 5], address: Option
, anonymous: bool, @@ -812,11 +823,11 @@ pub(crate) fn handle_expect_emit( .expected_emits .insert(index_to_fill_or_check, (event_to_fill_or_check, count_map)); } else { - interpreter.instruction_result = InstructionResult::Revert; - interpreter.next_action = InterpreterAction::Return { + interpreter.control.instruction_result = InstructionResult::Revert; + interpreter.control.next_action = InterpreterAction::Return { result: InterpreterResult { output: Error::encode("use vm.expectEmitAnonymous to match anonymous events"), - gas: interpreter.gas, + gas: interpreter.control.gas, result: InstructionResult::Revert, }, }; @@ -956,7 +967,7 @@ fn expect_create( fn expect_revert( state: &mut Cheatcodes, reason: Option<&[u8]>, - depth: u64, + depth: usize, cheatcode: bool, partial_match: bool, reverter: Option
, diff --git a/crates/cheatcodes/src/utils.rs b/crates/cheatcodes/src/utils.rs index 4735ffaa41087..97b5c7ecd213a 100644 --- a/crates/cheatcodes/src/utils.rs +++ b/crates/cheatcodes/src/utils.rs @@ -8,6 +8,7 @@ use foundry_common::ens::namehash; use foundry_evm_core::constants::DEFAULT_CREATE2_DEPLOYER; use proptest::prelude::Strategy; use rand::{seq::SliceRandom, Rng, RngCore}; +use revm::context::JournalTr; /// Contains locations of traces ignored via cheatcodes. /// @@ -232,9 +233,9 @@ impl Cheatcode for copyStorageCall { "target address cannot have arbitrary storage" ); - if let Ok(from_account) = ccx.load_account(*from) { + if let Ok(from_account) = ccx.ecx.journaled_state.load_account(*from) { let from_storage = from_account.storage.clone(); - if let Ok(mut to_account) = ccx.load_account(*to) { + if let Ok(mut to_account) = ccx.ecx.journaled_state.load_account(*to) { to_account.storage = from_storage; if let Some(ref mut arbitrary_storage) = &mut ccx.state.arbitrary_storage { arbitrary_storage.mark_copy(from, to); diff --git a/crates/common/fmt/Cargo.toml b/crates/common/fmt/Cargo.toml index 2a56b3b10e010..cf4aa5a7ba765 100644 --- a/crates/common/fmt/Cargo.toml +++ b/crates/common/fmt/Cargo.toml @@ -25,7 +25,7 @@ alloy-serde.workspace = true serde.workspace = true serde_json.workspace = true chrono.workspace = true -revm-primitives.workspace = true +revm.workspace = true comfy-table.workspace = true yansi.workspace = true diff --git a/crates/common/fmt/src/eof.rs b/crates/common/fmt/src/eof.rs index 1527d42bb77bc..692d745ebdd29 100644 --- a/crates/common/fmt/src/eof.rs +++ b/crates/common/fmt/src/eof.rs @@ -1,5 +1,6 @@ +use alloy_primitives::hex; use comfy_table::{modifiers::UTF8_ROUND_CORNERS, ContentArrangement, Table}; -use revm_primitives::{ +use revm::bytecode::{ Eof, }; use std::fmt::{self, Write}; @@ -15,11 +16,12 @@ pub fn pretty_eof(eof: &Eof) -> Result { sum_code_sizes: _, sum_container_sizes: _, }, - body: - EofBody { types_section, code_section, container_section, data_section, is_data_filled: _ }, + body, raw: _, } = eof; + let EofBody { code_info, code_section, container_section, data_section, .. } = &body; + let mut result = String::new(); let mut table = Table::new(); @@ -42,13 +44,13 @@ pub fn pretty_eof(eof: &Eof) -> Result { table.apply_modifier(UTF8_ROUND_CORNERS); table.set_content_arrangement(ContentArrangement::Dynamic); table.set_header(vec!["", "Inputs", "Outputs", "Max stack height", "Code"]); - for (idx, (code, type_section)) in code_section.iter().zip(types_section).enumerate() { + for (idx, type_section) in code_info.iter().enumerate() { table.add_row(vec![ &idx.to_string(), &type_section.inputs.to_string(), &type_section.outputs.to_string(), &type_section.max_stack_size.to_string(), - &code.to_string(), + &hex::encode_prefixed(body.code(idx).unwrap_or_default()), ]); } diff --git a/crates/common/fmt/src/ui.rs b/crates/common/fmt/src/ui.rs index 16600324bcb0f..89e18e5620183 100644 --- a/crates/common/fmt/src/ui.rs +++ b/crates/common/fmt/src/ui.rs @@ -12,7 +12,7 @@ use alloy_rpc_types::{ AccessListItem, Block, BlockTransactions, Header, Log, Transaction, TransactionReceipt, }; use alloy_serde::{OtherFields, WithOtherFields}; -use revm_primitives::SignedAuthorization; +use revm::context_interface::transaction::SignedAuthorization; use serde::Deserialize; /// length of the name column for pretty formatting `{:>20}{value}` diff --git a/crates/config/Cargo.toml b/crates/config/Cargo.toml index 816f06054734f..7f938e3911a20 100644 --- a/crates/config/Cargo.toml +++ b/crates/config/Cargo.toml @@ -19,7 +19,8 @@ foundry-compilers = { workspace = true, features = ["svm-solc"] } alloy-chains = { workspace = true, features = ["serde"] } alloy-primitives = { workspace = true, features = ["serde"] } -revm-primitives.workspace = true + +revm.workspace = true solar-parse.workspace = true diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 2abb5a04cb233..a0f0df4c8637f 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -9,7 +9,7 @@ extern crate tracing; use crate::cache::StorageCachingConfig; -use alloy_primitives::{address, Address, B256, U256}; +use alloy_primitives::{address, map::AddressHashMap, Address, FixedBytes, B256, U256}; use eyre::{ContextCompat, WrapErr}; use figment::{ providers::{Env, Format, Serialized, Toml}, @@ -39,7 +39,7 @@ use foundry_compilers::{ RestrictionsWithVersion, VyperLanguage, }; use regex::Regex; -use revm_primitives::{map::AddressHashMap, FixedBytes, SpecId}; +use revm::primitives::hardfork::SpecId; use semver::Version; use serde::{Deserialize, Serialize, Serializer}; use std::{ diff --git a/crates/config/src/utils.rs b/crates/config/src/utils.rs index 86b25d1043797..bcb20ab698afb 100644 --- a/crates/config/src/utils.rs +++ b/crates/config/src/utils.rs @@ -7,7 +7,7 @@ use foundry_compilers::artifacts::{ remappings::{Remapping, RemappingError}, EvmVersion, }; -use revm_primitives::SpecId; +use revm::primitives::hardfork::SpecId; use serde::{de::Error, Deserialize, Deserializer}; use std::{ io, diff --git a/crates/debugger/src/dump.rs b/crates/debugger/src/dump.rs index 83af7b0e777f7..2d50b4079ed4b 100644 --- a/crates/debugger/src/dump.rs +++ b/crates/debugger/src/dump.rs @@ -5,7 +5,7 @@ use foundry_compilers::{ artifacts::sourcemap::{Jump, SourceElement}, multi::MultiCompilerLanguage, }; -use foundry_evm_core::utils::PcIcMap; +use foundry_evm_core::ic::PcIcMap; use foundry_evm_traces::debug::{ArtifactData, ContractSources, SourceData}; use serde::Serialize; use std::{collections::HashMap, path::Path}; diff --git a/crates/debugger/src/op.rs b/crates/debugger/src/op.rs index bc8e96ccb3997..8e2edce964ae9 100644 --- a/crates/debugger/src/op.rs +++ b/crates/debugger/src/op.rs @@ -1,5 +1,5 @@ use alloy_primitives::Bytes; -use revm::interpreter::opcode; +use revm::bytecode::opcode; /// Named parameter of an EVM opcode. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] diff --git a/crates/debugger/src/tui/context.rs b/crates/debugger/src/tui/context.rs index 0c61a1fcd41c4..a2a4c987a78d6 100644 --- a/crates/debugger/src/tui/context.rs +++ b/crates/debugger/src/tui/context.rs @@ -4,7 +4,7 @@ use crate::{debugger::DebuggerContext, DebugNode, ExitReason}; use alloy_primitives::{hex, Address}; use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind}; use foundry_evm_core::buffer::BufferKind; -use revm::interpreter::OpCode; +use revm::bytecode::opcode::OpCode; use revm_inspectors::tracing::types::{CallKind, CallTraceStep}; use std::ops::ControlFlow; diff --git a/crates/evm/core/Cargo.toml b/crates/evm/core/Cargo.toml index 5730e6fb3ab4a..45097ca47f1fa 100644 --- a/crates/evm/core/Cargo.toml +++ b/crates/evm/core/Cargo.toml @@ -20,6 +20,7 @@ foundry-config.workspace = true foundry-evm-abi.workspace = true alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] } +alloy-evm.workspace = true alloy-genesis.workspace = true alloy-json-abi.workspace = true alloy-primitives = { workspace = true, features = [ @@ -43,11 +44,13 @@ revm = { workspace = true, features = [ "optional_block_gas_limit", "optional_no_base_fee", "arbitrary", - "optimism", "c-kzg", "blst", + "secp256r1", ] } revm-inspectors.workspace = true +op-revm.workspace = true +alloy-op-evm.workspace = true auto_impl.workspace = true eyre.workspace = true diff --git a/crates/evm/core/src/backend/cow.rs b/crates/evm/core/src/backend/cow.rs index 3ffb9fc84f3cd..4220150e6536b 100644 --- a/crates/evm/core/src/backend/cow.rs +++ b/crates/evm/core/src/backend/cow.rs @@ -3,23 +3,25 @@ use super::BackendError; use crate::{ backend::{ - diagnostic::RevertDiagnostic, Backend, DatabaseExt, LocalForkId, RevertStateSnapshotAction, + diagnostic::RevertDiagnostic, Backend, DatabaseExt, JournaledState, LocalForkId, + RevertStateSnapshotAction, }, fork::{CreateFork, ForkId}, - InspectorExt, + AsEnvMut, Env, EnvMut, InspectorExt, }; +use alloy_evm::Evm; use alloy_genesis::GenesisAccount; use alloy_primitives::{Address, B256, U256}; use alloy_rpc_types::TransactionRequest; use eyre::WrapErr; use foundry_fork_db::DatabaseError; use revm::{ - db::DatabaseRef, - primitives::{ - Account, AccountInfo, Bytecode, Env, EnvWithHandlerCfg, HashMap as Map, ResultAndState, - SpecId, - }, - Database, DatabaseCommit, JournaledState, + bytecode::Bytecode, + context_interface::result::ResultAndState, + database::DatabaseRef, + primitives::{hardfork::SpecId, HashMap as Map}, + state::{Account, AccountInfo}, + Database, DatabaseCommit, }; use std::{borrow::Cow, collections::BTreeMap}; @@ -54,7 +56,7 @@ pub struct CowBackend<'a> { impl<'a> CowBackend<'a> { /// Creates a new `CowBackend` with the given `Backend`. pub fn new_borrowed(backend: &'a Backend) -> Self { - Self { backend: Cow::Borrowed(backend), is_initialized: false, spec_id: SpecId::LATEST } + Self { backend: Cow::Borrowed(backend), is_initialized: false, spec_id: SpecId::default() } } /// Executes the configured transaction of the `env` without committing state changes @@ -64,18 +66,19 @@ impl<'a> CowBackend<'a> { #[instrument(name = "inspect", level = "debug", skip_all)] pub fn inspect( &mut self, - env: &mut EnvWithHandlerCfg, + env: &mut Env, inspector: &mut I, ) -> eyre::Result { // this is a new call to inspect with a new env, so even if we've cloned the backend // already, we reset the initialized state self.is_initialized = false; - self.spec_id = env.handler_cfg.spec_id; - let mut evm = crate::utils::new_evm_with_inspector(self, env.clone(), inspector); + self.spec_id = env.evm_env.cfg_env.spec; + + let mut evm = crate::evm::new_evm_with_inspector(self, env.to_owned(), inspector); - let res = evm.transact().wrap_err("EVM error")?; + let res = evm.transact(env.tx.clone()).wrap_err("EVM error")?; - env.env = evm.context.evm.inner.env; + *env = evm.as_env_mut().to_owned(); Ok(res) } @@ -90,10 +93,11 @@ impl<'a> CowBackend<'a> { /// Returns a mutable instance of the Backend. /// /// If this is the first time this is called, the backed is cloned and initialized. - fn backend_mut(&mut self, env: &Env) -> &mut Backend { + fn backend_mut(&mut self, env: &EnvMut<'_>) -> &mut Backend { if !self.is_initialized { let backend = self.backend.to_mut(); - let env = EnvWithHandlerCfg::new_with_spec_id(Box::new(env.clone()), self.spec_id); + let mut env = env.to_owned(); + env.evm_env.cfg_env.spec = self.spec_id; backend.initialize(&env); self.is_initialized = true; return backend @@ -111,7 +115,7 @@ impl<'a> CowBackend<'a> { } impl DatabaseExt for CowBackend<'_> { - fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { + fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &mut EnvMut<'_>) -> U256 { self.backend_mut(env).snapshot_state(journaled_state, env) } @@ -119,7 +123,7 @@ impl DatabaseExt for CowBackend<'_> { &mut self, id: U256, journaled_state: &JournaledState, - current: &mut Env, + current: &mut EnvMut<'_>, action: RevertStateSnapshotAction, ) -> Option { self.backend_mut(current).revert_state(id, journaled_state, current, action) @@ -154,7 +158,7 @@ impl DatabaseExt for CowBackend<'_> { fn select_fork( &mut self, id: LocalForkId, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { self.backend_mut(env).select_fork(id, env, journaled_state) @@ -164,7 +168,7 @@ impl DatabaseExt for CowBackend<'_> { &mut self, id: Option, block_number: u64, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { self.backend_mut(env).roll_fork(id, block_number, env, journaled_state) @@ -174,7 +178,7 @@ impl DatabaseExt for CowBackend<'_> { &mut self, id: Option, transaction: B256, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { self.backend_mut(env).roll_fork_to_transaction(id, transaction, env, journaled_state) @@ -184,21 +188,32 @@ impl DatabaseExt for CowBackend<'_> { &mut self, id: Option, transaction: B256, - env: Env, + mut env: Env, journaled_state: &mut JournaledState, inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { - self.backend_mut(&env).transact(id, transaction, env, journaled_state, inspector) + self.backend_mut(&env.as_env_mut()).transact( + id, + transaction, + env, + journaled_state, + inspector, + ) } fn transact_from_tx( &mut self, transaction: &TransactionRequest, - env: Env, + mut env: Env, journaled_state: &mut JournaledState, inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { - self.backend_mut(&env).transact_from_tx(transaction, env, journaled_state, inspector) + self.backend_mut(&env.as_env_mut()).transact_from_tx( + transaction, + env, + journaled_state, + inspector, + ) } fn active_fork_id(&self) -> Option { @@ -230,7 +245,7 @@ impl DatabaseExt for CowBackend<'_> { allocs: &BTreeMap, journaled_state: &mut JournaledState, ) -> Result<(), BackendError> { - self.backend_mut(&Env::default()).load_allocs(allocs, journaled_state) + self.backend_mut(&Env::default().as_env_mut()).load_allocs(allocs, journaled_state) } fn clone_account( @@ -239,7 +254,11 @@ impl DatabaseExt for CowBackend<'_> { target: &Address, journaled_state: &mut JournaledState, ) -> Result<(), BackendError> { - self.backend_mut(&Env::default()).clone_account(source, target, journaled_state) + self.backend_mut(&Env::default().as_env_mut()).clone_account( + source, + target, + journaled_state, + ) } fn is_persistent(&self, acc: &Address) -> bool { diff --git a/crates/evm/core/src/backend/error.rs b/crates/evm/core/src/backend/error.rs index 1dabeafded152..42456cceadd16 100644 --- a/crates/evm/core/src/backend/error.rs +++ b/crates/evm/core/src/backend/error.rs @@ -1,6 +1,6 @@ use alloy_primitives::Address; pub use foundry_fork_db::{DatabaseError, DatabaseResult}; -use revm::primitives::EVMError; +use revm::context_interface::result::EVMError; use std::convert::Infallible; pub type BackendResult = Result; @@ -59,7 +59,6 @@ impl> From> for BackendError { EVMError::Database(err) => err.into(), EVMError::Custom(err) => Self::msg(err), EVMError::Header(err) => Self::msg(err.to_string()), - EVMError::Precompile(err) => Self::msg(err), EVMError::Transaction(err) => Self::msg(err.to_string()), } } diff --git a/crates/evm/core/src/backend/in_memory_db.rs b/crates/evm/core/src/backend/in_memory_db.rs index c1956f96eb54f..0ffa718fb3671 100644 --- a/crates/evm/core/src/backend/in_memory_db.rs +++ b/crates/evm/core/src/backend/in_memory_db.rs @@ -4,8 +4,10 @@ use crate::state_snapshot::StateSnapshots; use alloy_primitives::{Address, B256, U256}; use foundry_fork_db::DatabaseError; use revm::{ - db::{CacheDB, DatabaseRef, EmptyDB}, - primitives::{Account, AccountInfo, Bytecode, HashMap as Map}, + bytecode::Bytecode, + database::{CacheDB, DatabaseRef, EmptyDB}, + primitives::HashMap as Map, + state::{Account, AccountInfo}, Database, DatabaseCommit, }; diff --git a/crates/evm/core/src/backend/mod.rs b/crates/evm/core/src/backend/mod.rs index 24eab386ee495..49716cd38c84a 100644 --- a/crates/evm/core/src/backend/mod.rs +++ b/crates/evm/core/src/backend/mod.rs @@ -2,11 +2,13 @@ use crate::{ constants::{CALLER, CHEATCODE_ADDRESS, DEFAULT_CREATE2_DEPLOYER, TEST_CONTRACT_ADDRESS}, + evm::new_evm_with_inspector, fork::{CreateFork, ForkId, MultiFork}, state_snapshot::StateSnapshots, - utils::{configure_tx_env, configure_tx_req_env, new_evm_with_inspector}, - InspectorExt, + utils::{configure_tx_env, configure_tx_req_env}, + AsEnvMut, Env, EnvMut, InspectorExt, }; +use alloy_evm::Evm; use alloy_genesis::GenesisAccount; use alloy_network::{AnyRpcBlock, AnyTxEnvelope, TransactionResponse}; use alloy_primitives::{keccak256, uint, Address, TxKind, B256, U256}; @@ -15,14 +17,15 @@ use eyre::Context; use foundry_common::{is_known_system_sender, SYSTEM_TRANSACTION_TYPE}; pub use foundry_fork_db::{cache::BlockchainDbMeta, BlockchainDb, SharedBackend}; use revm::{ - db::{CacheDB, DatabaseRef}, - inspectors::NoOpInspector, + bytecode::Bytecode, + context::JournalInner, + context_interface::{block::BlobExcessGasAndPrice, result::ResultAndState}, + database::{CacheDB, DatabaseRef}, + inspector::NoOpInspector, precompile::{PrecompileSpecId, Precompiles}, - primitives::{ - Account, AccountInfo, BlobExcessGasAndPrice, Bytecode, Env, EnvWithHandlerCfg, EvmState, - EvmStorageSlot, HashMap as Map, Log, ResultAndState, SpecId, KECCAK_EMPTY, - }, - Database, DatabaseCommit, JournaledState, + primitives::{hardfork::SpecId, HashMap as Map, Log, KECCAK_EMPTY}, + state::{Account, AccountInfo, EvmState, EvmStorageSlot}, + Database, DatabaseCommit, JournalEntry, }; use std::{ collections::{BTreeMap, HashMap, HashSet}, @@ -68,6 +71,8 @@ const DEFAULT_PERSISTENT_ACCOUNTS: [Address; 3] = pub const GLOBAL_FAIL_SLOT: U256 = uint!(0x6661696c65640000000000000000000000000000000000000000000000000000_U256); +pub type JournaledState = JournalInner; + /// An extension trait that allows us to easily extend the `revm::Inspector` capabilities #[auto_impl::auto_impl(&mut)] pub trait DatabaseExt: Database + DatabaseCommit { @@ -76,7 +81,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { /// A state snapshot is associated with a new unique id that's created for the snapshot. /// State snapshots can be reverted: [DatabaseExt::revert_state], however, depending on the /// [RevertStateSnapshotAction], it will keep the snapshot alive or delete it. - fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &Env) -> U256; + fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &mut EnvMut<'_>) -> U256; /// Reverts the snapshot if it exists /// @@ -94,7 +99,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { &mut self, id: U256, journaled_state: &JournaledState, - env: &mut Env, + env: &mut EnvMut<'_>, action: RevertStateSnapshotAction, ) -> Option; @@ -113,7 +118,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { fn create_select_fork( &mut self, fork: CreateFork, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result { let id = self.create_fork(fork)?; @@ -127,7 +132,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { fn create_select_fork_at_transaction( &mut self, fork: CreateFork, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, transaction: B256, ) -> eyre::Result { @@ -158,7 +163,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { fn select_fork( &mut self, id: LocalForkId, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()>; @@ -173,7 +178,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { &mut self, id: Option, block_number: u64, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()>; @@ -189,7 +194,7 @@ pub trait DatabaseExt: Database + DatabaseCommit { &mut self, id: Option, transaction: B256, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()>; @@ -433,7 +438,7 @@ pub struct Backend { mem_db: FoundryEvmInMemoryDB, /// The journaled_state to use to initialize new forks with /// - /// The way [`revm::JournaledState`] works is, that it holds the "hot" accounts loaded from the + /// The way [`JournaledState`] works is, that it holds the "hot" accounts loaded from the /// underlying `Database` that feeds the Account and State data to the journaled_state so it /// can apply changes to the state while the EVM executes. /// @@ -738,11 +743,11 @@ impl Backend { /// Initializes settings we need to keep track of. /// /// We need to track these mainly to prevent issues when switching between different evms - pub(crate) fn initialize(&mut self, env: &EnvWithHandlerCfg) { + pub(crate) fn initialize(&mut self, env: &Env) { self.set_caller(env.tx.caller); - self.set_spec_id(env.handler_cfg.spec_id); + self.set_spec_id(env.evm_env.cfg_env.spec); - let test_contract = match env.tx.transact_to { + let test_contract = match env.tx.kind { TxKind::Call(to) => to, TxKind::Create => { let nonce = self @@ -755,11 +760,6 @@ impl Backend { self.set_test_contract(test_contract); } - /// Returns the `EnvWithHandlerCfg` with the current `spec_id` set. - fn env_with_handler_cfg(&self, env: Env) -> EnvWithHandlerCfg { - EnvWithHandlerCfg::new_with_spec_id(Box::new(env), self.inner.spec_id) - } - /// Executes the configured test call of the `env` without committing state changes. /// /// Note: in case there are any cheatcodes executed that modify the environment, this will @@ -767,15 +767,15 @@ impl Backend { #[instrument(name = "inspect", level = "debug", skip_all)] pub fn inspect( &mut self, - env: &mut EnvWithHandlerCfg, + env: &mut Env, inspector: &mut I, ) -> eyre::Result { self.initialize(env); - let mut evm = crate::utils::new_evm_with_inspector(self, env.clone(), inspector); + let mut evm = crate::evm::new_evm_with_inspector(self, env.to_owned(), inspector); - let res = evm.transact().wrap_err("EVM error")?; + let res = evm.transact(env.tx.clone()).wrap_err("EVM error")?; - env.env = evm.context.evm.inner.env; + *env = evm.as_env_mut().to_owned(); Ok(res) } @@ -869,7 +869,7 @@ impl Backend { pub fn replay_until( &mut self, id: LocalForkId, - env: Env, + mut env: Env, tx_hash: B256, journaled_state: &mut JournaledState, ) -> eyre::Result>> { @@ -878,9 +878,8 @@ impl Backend { let persistent_accounts = self.inner.persistent_accounts.clone(); let fork_id = self.ensure_fork_id(id)?.clone(); - let env = self.env_with_handler_cfg(env); let fork = self.inner.get_fork_by_id_mut(id)?; - let full_block = fork.db.db.get_full_block(env.block.number.to::())?; + let full_block = fork.db.db.get_full_block(env.evm_env.block_env.number)?; for tx in full_block.inner.transactions.txns() { // System transactions such as on L2s don't contain any pricing info so we skip them @@ -900,7 +899,7 @@ impl Backend { commit_transaction( &tx.inner, - env.clone(), + &mut env.as_env_mut(), journaled_state, fork, &fork_id, @@ -914,12 +913,12 @@ impl Backend { } impl DatabaseExt for Backend { - fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &Env) -> U256 { + fn snapshot_state(&mut self, journaled_state: &JournaledState, env: &mut EnvMut<'_>) -> U256 { trace!("create snapshot"); let id = self.inner.state_snapshots.insert(BackendStateSnapshot::new( self.create_db_snapshot(), journaled_state.clone(), - env.clone(), + env.to_owned(), )); trace!(target: "backend", "Created new snapshot {}", id); id @@ -929,7 +928,7 @@ impl DatabaseExt for Backend { &mut self, id: U256, current_state: &JournaledState, - current: &mut Env, + current: &mut EnvMut<'_>, action: RevertStateSnapshotAction, ) -> Option { trace!(?id, "revert snapshot"); @@ -970,7 +969,7 @@ impl DatabaseExt for Backend { .map(|acc| acc.info.clone()) .unwrap_or_default(); - if !fork.db.accounts.contains_key(&caller) { + if !fork.db.cache.accounts.contains_key(&caller) { // update the caller account which is required by the evm fork.db.insert_account_info(caller, caller_account.clone()); } @@ -981,7 +980,7 @@ impl DatabaseExt for Backend { } } - update_current_env_with_fork_env(current, env); + update_current_env_with_fork_env(&mut current.as_env_mut(), env); trace!(target: "backend", "Reverted snapshot {}", id); Some(journaled_state) @@ -1027,7 +1026,7 @@ impl DatabaseExt for Backend { self.roll_fork_to_transaction( Some(id), transaction, - &mut env, + &mut env.as_env_mut(), &mut self.inner.new_journaled_state(), )?; Ok(id) @@ -1038,7 +1037,7 @@ impl DatabaseExt for Backend { fn select_fork( &mut self, id: LocalForkId, - env: &mut Env, + env: &mut EnvMut<'_>, active_journaled_state: &mut JournaledState, ) -> eyre::Result<()> { trace!(?id, "select fork"); @@ -1127,7 +1126,7 @@ impl DatabaseExt for Backend { .map(|acc| acc.info.clone()) .unwrap_or_default(); - if !fork.db.accounts.contains_key(&caller) { + if !fork.db.cache.accounts.contains_key(&caller) { // update the caller account which is required by the evm fork.db.insert_account_info(caller, caller_account.clone()); } @@ -1153,7 +1152,7 @@ impl DatabaseExt for Backend { &mut self, id: Option, block_number: u64, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { trace!(?id, ?block_number, "roll fork"); @@ -1203,7 +1202,7 @@ impl DatabaseExt for Backend { ); } } else { - let _ = active.journaled_state.load_account(*addr, &mut active.db); + let _ = active.journaled_state.load_account(&mut active.db, *addr); } } @@ -1217,7 +1216,7 @@ impl DatabaseExt for Backend { &mut self, id: Option, transaction: B256, - env: &mut Env, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, ) -> eyre::Result<()> { trace!(?id, ?transaction, "roll fork to transaction"); @@ -1231,9 +1230,9 @@ impl DatabaseExt for Backend { update_env_block(env, &block); - // replay all transactions that came before - let env = env.clone(); + let env = env.to_owned(); + // replay all transactions that came before self.replay_until(id, env, transaction, journaled_state)?; Ok(()) @@ -1265,13 +1264,12 @@ impl DatabaseExt for Backend { // So we modify the env to match the transaction's block. let (_fork_block, block) = self.get_block_number_and_block_for_transaction(id, transaction)?; - update_env_block(&mut env, &block); + update_env_block(&mut env.as_env_mut(), &block); - let env = self.env_with_handler_cfg(env); let fork = self.inner.get_fork_by_id_mut(id)?; commit_transaction( &tx, - env, + &mut env.as_env_mut(), journaled_state, fork, &fork_id, @@ -1292,13 +1290,12 @@ impl DatabaseExt for Backend { self.commit(journaled_state.state.clone()); let res = { - configure_tx_req_env(&mut env, tx, None)?; - let env = self.env_with_handler_cfg(env); + configure_tx_req_env(&mut env.as_env_mut(), tx, None)?; let mut db = self.clone(); - let mut evm = new_evm_with_inspector(&mut db, env, inspector); - evm.context.evm.journaled_state.depth = journaled_state.depth + 1; - evm.transact()? + let mut evm = new_evm_with_inspector(&mut db, env.to_owned(), inspector); + evm.journaled_state.depth = journaled_state.depth + 1; + evm.transact(env.tx)? }; self.commit(res.state); @@ -1405,7 +1402,7 @@ impl DatabaseExt for Backend { ) -> Result<(), BackendError> { // Fetch the account from the journaled state. Will create a new account if it does // not already exist. - let mut state_acc = journaled_state.load_account(*target, self)?; + let mut state_acc = journaled_state.load_account(self, *target)?; // Set the account's bytecode and code hash, if the `bytecode` field is present. if let Some(bytecode) = source.code.as_ref() { @@ -1439,7 +1436,7 @@ impl DatabaseExt for Backend { state_acc.info.balance = source.balance; // Touch the account to ensure the loaded information persists if called in `setUp`. - journaled_state.touch(target); + journaled_state.touch(*target); Ok(()) } @@ -1474,9 +1471,9 @@ impl DatabaseExt for Backend { fn set_blockhash(&mut self, block_number: U256, block_hash: B256) { if let Some(db) = self.active_fork_db_mut() { - db.block_hashes.insert(block_number, block_hash); + db.cache.block_hashes.insert(block_number.saturating_to(), block_hash); } else { - self.mem_db.block_hashes.insert(block_number, block_hash); + self.mem_db.cache.block_hashes.insert(block_number.saturating_to(), block_hash); } } } @@ -1803,7 +1800,13 @@ impl BackendInner { /// Returns a new, empty, `JournaledState` with set precompiles pub fn new_journaled_state(&self) -> JournaledState { - JournaledState::new(self.spec_id, self.precompiles().addresses().copied().collect()) + let mut journal = { + let mut journal_inner = JournalInner::new(); + journal_inner.set_spec_id(self.spec_id); + journal_inner + }; + journal.precompiles.extend(self.precompiles().addresses().copied()); + journal } } @@ -1819,7 +1822,7 @@ impl Default for BackendInner { caller: None, next_fork_id: Default::default(), persistent_accounts: Default::default(), - spec_id: SpecId::LATEST, + spec_id: SpecId::default(), // grant the cheatcode,default test and caller address access to execute cheatcodes // itself cheatcode_access_accounts: HashSet::from([ @@ -1832,9 +1835,9 @@ impl Default for BackendInner { } /// This updates the currently used env with the fork's environment -pub(crate) fn update_current_env_with_fork_env(current: &mut Env, fork: Env) { - current.block = fork.block; - current.cfg = fork.cfg; +pub(crate) fn update_current_env_with_fork_env(current: &mut EnvMut<'_>, fork: Env) { + *current.block = fork.evm_env.block_env; + *current.cfg = fork.evm_env.cfg_env; current.tx.chain_id = fork.tx.chain_id; } @@ -1886,17 +1889,17 @@ fn merge_db_account_data( ) { trace!(?addr, "merging database data"); - let Some(acc) = active.accounts.get(&addr) else { return }; + let Some(acc) = active.cache.accounts.get(&addr) else { return }; // port contract cache over - if let Some(code) = active.contracts.get(&acc.info.code_hash) { + if let Some(code) = active.cache.contracts.get(&acc.info.code_hash) { trace!("merging contract cache"); - fork_db.contracts.insert(acc.info.code_hash, code.clone()); + fork_db.cache.contracts.insert(acc.info.code_hash, code.clone()); } // port account storage over use std::collections::hash_map::Entry; - match fork_db.accounts.entry(addr) { + match fork_db.cache.accounts.entry(addr) { Entry::Vacant(vacant) => { trace!("target account not present - inserting from active"); // if the fork_db doesn't have the target account @@ -1923,14 +1926,14 @@ fn is_contract_in_state(journaled_state: &JournaledState, acc: Address) -> bool } /// Updates the env's block with the block's data -fn update_env_block(env: &mut Env, block: &AnyRpcBlock) { - env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.beneficiary; +fn update_env_block(env: &mut EnvMut<'_>, block: &AnyRpcBlock) { + env.block.timestamp = block.header.timestamp; + env.block.beneficiary = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); - env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); - env.block.gas_limit = U256::from(block.header.gas_limit); - env.block.number = U256::from(block.header.number); + env.block.basefee = block.header.base_fee_per_gas.unwrap_or_default(); + env.block.gas_limit = block.header.gas_limit; + env.block.number = block.header.number; if let Some(excess_blob_gas) = block.header.excess_blob_gas { env.block.blob_excess_gas_and_price = Some(BlobExcessGasAndPrice::new(excess_blob_gas, false)); @@ -1941,14 +1944,14 @@ fn update_env_block(env: &mut Env, block: &AnyRpcBlock) { /// state, with an inspector. fn commit_transaction( tx: &Transaction, - mut env: EnvWithHandlerCfg, + env: &mut EnvMut<'_>, journaled_state: &mut JournaledState, fork: &mut Fork, fork_id: &ForkId, persistent_accounts: &HashSet
, inspector: &mut dyn InspectorExt, ) -> eyre::Result<()> { - configure_tx_env(&mut env.env, tx); + configure_tx_env(env, tx); let now = Instant::now(); let res = { @@ -1957,10 +1960,10 @@ fn commit_transaction( let depth = journaled_state.depth; let mut db = Backend::new_with_fork(fork_id, fork, journaled_state)?; - let mut evm = crate::utils::new_evm_with_inspector(&mut db as _, env, inspector); + let mut evm = crate::evm::new_evm_with_inspector(&mut db as _, env.to_owned(), inspector); // Adjust inner EVM depth to ensure that inspectors receive accurate data. - evm.context.evm.inner.journaled_state.depth = depth + 1; - evm.transact().wrap_err("backend: failed committing transaction")? + evm.journaled_state.depth = depth + 1; + evm.transact(env.tx.clone()).wrap_err("backend: failed committing transaction")? }; trace!(elapsed = ?now.elapsed(), "transacted transaction"); @@ -2012,7 +2015,7 @@ mod tests { use foundry_common::provider::get_http_provider; use foundry_config::{Config, NamedChain}; use foundry_fork_db::cache::{BlockchainDb, BlockchainDbMeta}; - use revm::DatabaseRef; + use revm::database::DatabaseRef; const ENDPOINT: Option<&str> = option_env!("ETH_RPC_URL"); @@ -2053,8 +2056,7 @@ mod tests { } drop(backend); - let meta = - BlockchainDbMeta { cfg_env: env.cfg, block_env: env.block, hosts: Default::default() }; + let meta = BlockchainDbMeta { block_env: env.evm_env.block_env, hosts: Default::default() }; let db = BlockchainDb::new( meta, diff --git a/crates/evm/core/src/backend/snapshot.rs b/crates/evm/core/src/backend/snapshot.rs index 36c4657c2618c..d26d9a55e750d 100644 --- a/crates/evm/core/src/backend/snapshot.rs +++ b/crates/evm/core/src/backend/snapshot.rs @@ -1,8 +1,10 @@ -use alloy_primitives::{map::AddressHashMap, B256, U256}; -use revm::{ - primitives::{AccountInfo, Env, HashMap}, - JournaledState, +use super::JournaledState; +use crate::Env; +use alloy_primitives::{ + map::{AddressHashMap, HashMap}, + B256, U256, }; +use revm::state::AccountInfo; use serde::{Deserialize, Serialize}; /// A minimal abstraction of a state at a certain point in time diff --git a/crates/evm/core/src/buffer.rs b/crates/evm/core/src/buffer.rs index 1db7420d78736..5cce0a91ad97b 100644 --- a/crates/evm/core/src/buffer.rs +++ b/crates/evm/core/src/buffer.rs @@ -1,5 +1,5 @@ use alloy_primitives::U256; -use revm::interpreter::opcode; +use revm::bytecode::opcode; /// Used to keep track of which buffer is currently active to be drawn by the debugger. #[derive(Debug, PartialEq)] diff --git a/crates/evm/core/src/either_evm.rs b/crates/evm/core/src/either_evm.rs new file mode 100644 index 0000000000000..1ee289d88a162 --- /dev/null +++ b/crates/evm/core/src/either_evm.rs @@ -0,0 +1,239 @@ +use alloy_evm::{eth::EthEvmContext, Database, EthEvm, Evm, EvmEnv}; +use alloy_op_evm::OpEvm; +use alloy_primitives::{Address, Bytes}; +use op_revm::{OpContext, OpHaltReason, OpSpecId, OpTransaction, OpTransactionError}; +use revm::{ + context::{ + result::{EVMError, ExecutionResult, HaltReason, ResultAndState}, + BlockEnv, TxEnv, + }, + handler::PrecompileProvider, + interpreter::InterpreterResult, + primitives::hardfork::SpecId, + DatabaseCommit, Inspector, +}; + +/// Alias for result type returned by [`Evm::transact`] methods. +type EitherEvmResult = + Result, EVMError>; + +/// Alias for result type returned by [`Evm::transact_commit`] methods. +type EitherExecResult = + Result, EVMError>; + +/// [`EitherEvm`] delegates its calls to one of the two evm implementations; either [`EthEvm`] or +/// [`OpEvm`]. +/// +/// Calls are delegated to [`OpEvm`] only if optimism is enabled. +/// +/// The call delegation is handled via its own implementation of the [`Evm`] trait. +/// +/// The [`Evm::transact`] and other such calls work over the [`OpTransaction`] type. +/// +/// However, the [`Evm::HaltReason`] and [`Evm::Error`] leverage the optimism [`OpHaltReason`] and +/// [`OpTransactionError`] as these are supersets of the eth types. This makes it easier to map eth +/// types to op types and also prevents ignoring of any error that maybe thrown by [`OpEvm`]. +#[allow(clippy::large_enum_variant)] +pub enum EitherEvm +where + DB: Database, +{ + /// [`EthEvm`] implementation. + Eth(EthEvm), + /// [`OpEvm`] implementation. + Op(OpEvm), +} + +impl EitherEvm +where + DB: Database, + I: Inspector> + Inspector>, + P: PrecompileProvider, Output = InterpreterResult> + + PrecompileProvider, Output = InterpreterResult>, +{ + /// Converts the [`EthEvm::transact`] result to [`EitherEvmResult`]. + fn map_eth_result( + &self, + result: Result, EVMError>, + ) -> EitherEvmResult { + match result { + Ok(result) => { + // Map the halt reason + Ok(result.map_haltreason(OpHaltReason::Base)) + } + Err(e) => Err(self.map_eth_err(e)), + } + } + + /// Converts the [`EthEvm::transact_commit`] result to [`EitherExecResult`]. + fn map_exec_result( + &self, + result: Result>, + ) -> EitherExecResult { + match result { + Ok(result) => { + // Map the halt reason + Ok(result.map_haltreason(OpHaltReason::Base)) + } + Err(e) => Err(self.map_eth_err(e)), + } + } + + /// Maps [`EVMError`] to [`EVMError`]. + fn map_eth_err(&self, err: EVMError) -> EVMError { + match err { + EVMError::Transaction(invalid_tx) => { + EVMError::Transaction(OpTransactionError::Base(invalid_tx)) + } + EVMError::Database(e) => EVMError::Database(e), + EVMError::Header(e) => EVMError::Header(e), + EVMError::Custom(e) => EVMError::Custom(e), + } + } +} + +impl Evm for EitherEvm +where + DB: Database, + I: Inspector> + Inspector>, + P: PrecompileProvider, Output = InterpreterResult> + + PrecompileProvider, Output = InterpreterResult>, +{ + type DB = DB; + type Error = EVMError; + type HaltReason = OpHaltReason; + type Tx = OpTransaction; + type Spec = SpecId; + + fn block(&self) -> &BlockEnv { + match self { + Self::Eth(evm) => evm.block(), + Self::Op(evm) => evm.block(), + } + } + + fn db_mut(&mut self) -> &mut Self::DB { + match self { + Self::Eth(evm) => evm.db_mut(), + Self::Op(evm) => evm.db_mut(), + } + } + + fn into_db(self) -> Self::DB + where + Self: Sized, + { + match self { + Self::Eth(evm) => evm.into_db(), + Self::Op(evm) => evm.into_db(), + } + } + + fn finish(self) -> (Self::DB, EvmEnv) + where + Self: Sized, + { + match self { + Self::Eth(evm) => evm.finish(), + Self::Op(evm) => { + let (db, env) = evm.finish(); + (db, map_env(env)) + } + } + } + + fn enable_inspector(&mut self) { + match self { + Self::Eth(evm) => evm.enable_inspector(), + Self::Op(evm) => evm.enable_inspector(), + } + } + + fn disable_inspector(&mut self) { + match self { + Self::Eth(evm) => evm.disable_inspector(), + Self::Op(evm) => evm.disable_inspector(), + } + } + + fn set_inspector_enabled(&mut self, enabled: bool) { + match self { + Self::Eth(evm) => evm.set_inspector_enabled(enabled), + Self::Op(evm) => evm.set_inspector_enabled(enabled), + } + } + + fn into_env(self) -> EvmEnv + where + Self: Sized, + { + match self { + Self::Eth(evm) => evm.into_env(), + Self::Op(evm) => map_env(evm.into_env()), + } + } + + fn transact( + &mut self, + tx: impl alloy_evm::IntoTxEnv, + ) -> Result, Self::Error> { + match self { + Self::Eth(evm) => { + let eth = evm.transact(tx.into_tx_env().base); + self.map_eth_result(eth) + } + Self::Op(evm) => evm.transact(tx), + } + } + + fn transact_commit( + &mut self, + tx: impl alloy_evm::IntoTxEnv, + ) -> Result, Self::Error> + where + Self::DB: DatabaseCommit, + { + match self { + Self::Eth(evm) => { + let eth = evm.transact_commit(tx.into_tx_env().base); + self.map_exec_result(eth) + } + Self::Op(evm) => evm.transact_commit(tx), + } + } + + fn transact_raw( + &mut self, + tx: Self::Tx, + ) -> Result, Self::Error> { + match self { + Self::Eth(evm) => { + let res = evm.transact_raw(tx.base); + self.map_eth_result(res) + } + Self::Op(evm) => evm.transact_raw(tx), + } + } + + fn transact_system_call( + &mut self, + caller: Address, + contract: Address, + data: Bytes, + ) -> Result, Self::Error> { + match self { + Self::Eth(evm) => { + let eth = evm.transact_system_call(caller, contract, data); + self.map_eth_result(eth) + } + Self::Op(evm) => evm.transact_system_call(caller, contract, data), + } + } +} + +/// Maps [`EvmEnv`] to [`EvmEnv`]. +fn map_env(env: EvmEnv) -> EvmEnv { + let eth_spec_id = env.spec_id().into_eth_spec(); + let cfg = env.cfg_env.with_spec(eth_spec_id); + EvmEnv { cfg_env: cfg, block_env: env.block_env } +} diff --git a/crates/evm/core/src/env.rs b/crates/evm/core/src/env.rs new file mode 100644 index 0000000000000..a7708f132380d --- /dev/null +++ b/crates/evm/core/src/env.rs @@ -0,0 +1,103 @@ +pub use alloy_evm::EvmEnv; +use revm::{ + context::{BlockEnv, CfgEnv, JournalInner, JournalTr, TxEnv}, + primitives::hardfork::SpecId, + Context, Database, Journal, JournalEntry, +}; + +/// Helper container type for [`EvmEnv`] and [`TxEnv`]. +#[derive(Clone, Debug, Default)] +pub struct Env { + pub evm_env: EvmEnv, + pub tx: TxEnv, +} + +/// Helper container type for [`EvmEnv`] and [`TxEnv`]. +impl Env { + pub fn default_with_spec_id(spec_id: SpecId) -> Self { + let mut cfg = CfgEnv::default(); + cfg.spec = spec_id; + + Self::from(cfg, BlockEnv::default(), TxEnv::default()) + } + + pub fn from(cfg: CfgEnv, block: BlockEnv, tx: TxEnv) -> Self { + Self { evm_env: EvmEnv { cfg_env: cfg, block_env: block }, tx } + } + + pub fn new_with_spec_id(cfg: CfgEnv, block: BlockEnv, tx: TxEnv, spec_id: SpecId) -> Self { + let mut cfg = cfg; + cfg.spec = spec_id; + + Self::from(cfg, block, tx) + } +} + +/// Helper struct with mutable references to the block and cfg environments. +pub struct EnvMut<'a> { + pub block: &'a mut BlockEnv, + pub cfg: &'a mut CfgEnv, + pub tx: &'a mut TxEnv, +} + +impl EnvMut<'_> { + /// Returns a copy of the environment. + pub fn to_owned(&self) -> Env { + Env { + evm_env: EvmEnv { cfg_env: self.cfg.to_owned(), block_env: self.block.to_owned() }, + tx: self.tx.to_owned(), + } + } +} + +pub trait AsEnvMut { + fn as_env_mut(&mut self) -> EnvMut<'_>; +} + +impl AsEnvMut for EnvMut<'_> { + fn as_env_mut(&mut self) -> EnvMut<'_> { + EnvMut { block: self.block, cfg: self.cfg, tx: self.tx } + } +} + +impl AsEnvMut for Env { + fn as_env_mut(&mut self) -> EnvMut<'_> { + EnvMut { + block: &mut self.evm_env.block_env, + cfg: &mut self.evm_env.cfg_env, + tx: &mut self.tx, + } + } +} + +impl, C> AsEnvMut + for Context +{ + fn as_env_mut(&mut self) -> EnvMut<'_> { + EnvMut { block: &mut self.block, cfg: &mut self.cfg, tx: &mut self.tx } + } +} + +pub trait ContextExt { + type DB: Database; + + fn as_db_env_and_journal( + &mut self, + ) -> (&mut Self::DB, &mut JournalInner, EnvMut<'_>); +} + +impl ContextExt + for Context, C> +{ + type DB = DB; + + fn as_db_env_and_journal( + &mut self, + ) -> (&mut Self::DB, &mut JournalInner, EnvMut<'_>) { + ( + &mut self.journaled_state.database, + &mut self.journaled_state.inner, + EnvMut { block: &mut self.block, cfg: &mut self.cfg, tx: &mut self.tx }, + ) + } +} diff --git a/crates/evm/core/src/evm.rs b/crates/evm/core/src/evm.rs new file mode 100644 index 0000000000000..0f2e678b2f3ae --- /dev/null +++ b/crates/evm/core/src/evm.rs @@ -0,0 +1,371 @@ +use std::ops::{Deref, DerefMut}; + +use crate::{ + backend::DatabaseExt, constants::DEFAULT_CREATE2_DEPLOYER_CODEHASH, Env, InspectorExt, +}; +use alloy_consensus::constants::KECCAK_EMPTY; +use alloy_evm::{eth::EthEvmContext, Evm, EvmEnv}; +use alloy_primitives::{Address, Bytes, U256}; +use foundry_fork_db::DatabaseError; +use revm::{ + context::{ + result::{EVMError, HaltReason, ResultAndState}, + BlockEnv, CfgEnv, ContextTr, CreateScheme, Evm as RevmEvm, JournalTr, TxEnv, + }, + handler::{ + instructions::EthInstructions, EthFrame, EthPrecompiles, FrameInitOrResult, FrameResult, + Handler, ItemOrResult, MainnetHandler, PrecompileProvider, + }, + inspector::InspectorHandler, + interpreter::{ + interpreter::EthInterpreter, return_ok, CallInputs, CallOutcome, CallScheme, CallValue, + CreateInputs, CreateOutcome, FrameInput, Gas, InputsImpl, InstructionResult, + InterpreterResult, + }, + primitives::hardfork::SpecId, + Context, ExecuteEvm, Journal, +}; + +pub struct FoundryPrecompiles { + inner: EthPrecompiles, +} + +impl FoundryPrecompiles { + pub fn new() -> Self { + Self { inner: EthPrecompiles::default() } + } +} + +impl Default for FoundryPrecompiles { + fn default() -> Self { + Self::new() + } +} + +impl PrecompileProvider for FoundryPrecompiles { + type Output = InterpreterResult; + + /// Set the spec for the precompiles. + fn set_spec(&mut self, spec: <::Cfg as revm::context::Cfg>::Spec) -> bool { + PrecompileProvider::::set_spec(&mut self.inner, spec) + } + + /// Run the precompile. + fn run( + &mut self, + context: &mut CTX, + address: &Address, + inputs: &InputsImpl, + is_static: bool, + gas_limit: u64, + ) -> Result, String> { + self.inner.run(context, address, inputs, is_static, gas_limit) + } + + /// Get the warm addresses. + fn warm_addresses(&self) -> Box> { + self.inner.warm_addresses() + } + + /// Check if the address is a precompile. + fn contains(&self, address: &Address) -> bool { + self.inner.contains(address) + } +} + +pub fn new_evm_with_inspector<'i, 'db, I: InspectorExt + ?Sized>( + db: &'db mut dyn DatabaseExt, + env: Env, + inspector: &'i mut I, +) -> FoundryEvm<'db, &'i mut I> { + let ctx = EthEvmContext { + journaled_state: { + let mut journal = Journal::new(db); + journal.set_spec_id(env.evm_env.cfg_env.spec); + journal + }, + block: env.evm_env.block_env, + cfg: env.evm_env.cfg_env, + tx: env.tx, + chain: (), + error: Ok(()), + }; + + FoundryEvm { + inner: RevmEvm::new_with_inspector( + ctx, + inspector, + EthInstructions::default(), + FoundryPrecompiles::default(), + ), + } +} + +pub fn new_evm_with_existing_context<'a>( + ctx: EthEvmContext<&'a mut dyn DatabaseExt>, + inspector: &'a mut dyn InspectorExt, +) -> FoundryEvm<'a, &'a mut dyn InspectorExt> { + FoundryEvm { + inner: RevmEvm::new_with_inspector( + ctx, + inspector, + EthInstructions::default(), + FoundryPrecompiles::default(), + ), + } +} + +fn get_create2_factory_call_inputs( + salt: U256, + inputs: &CreateInputs, + deployer: Address, +) -> CallInputs { + let calldata = [&salt.to_be_bytes::<32>()[..], &inputs.init_code[..]].concat(); + CallInputs { + caller: inputs.caller, + bytecode_address: deployer, + target_address: deployer, + scheme: CallScheme::Call, + value: CallValue::Transfer(inputs.value), + input: calldata.into(), + gas_limit: inputs.gas_limit, + is_static: false, + return_memory_offset: 0..0, + is_eof: false, + } +} + +pub struct FoundryEvm<'db, I: InspectorExt> { + #[allow(clippy::type_complexity)] + pub inner: RevmEvm< + EthEvmContext<&'db mut dyn DatabaseExt>, + I, + EthInstructions>, + FoundryPrecompiles, + >, +} + +impl FoundryEvm<'_, I> { + pub fn run_execution( + &mut self, + frame: FrameInput, + ) -> Result> { + let mut handler = FoundryHandler::<_>::default(); + + // Create first frame action + let frame = handler.inspect_first_frame_init(&mut self.inner, frame)?; + let frame_result = match frame { + ItemOrResult::Item(frame) => handler.inspect_run_exec_loop(&mut self.inner, frame)?, + ItemOrResult::Result(result) => result, + }; + + Ok(frame_result) + } +} + +impl<'db, I: InspectorExt> Evm for FoundryEvm<'db, I> { + type DB = &'db mut dyn DatabaseExt; + type Error = EVMError; + type HaltReason = HaltReason; + type Spec = SpecId; + type Tx = TxEnv; + + fn block(&self) -> &BlockEnv { + &self.inner.block + } + + fn db_mut(&mut self) -> &mut Self::DB { + self.inner.db() + } + + fn set_inspector_enabled(&mut self, _enabled: bool) { + unimplemented!("FoundryEvm is always inspecting") + } + + fn transact_raw( + &mut self, + tx: Self::Tx, + ) -> Result, Self::Error> { + let mut handler = FoundryHandler::<_>::default(); + self.inner.set_tx(tx); + handler.inspect_run(&mut self.inner) + } + + fn transact_system_call( + &mut self, + _caller: Address, + _contract: Address, + _data: Bytes, + ) -> Result, Self::Error> { + unimplemented!() + } + + fn finish(self) -> (Self::DB, EvmEnv) + where + Self: Sized, + { + let Context { block: block_env, cfg: cfg_env, journaled_state, .. } = self.inner.data.ctx; + + (journaled_state.database, EvmEnv { block_env, cfg_env }) + } +} + +impl<'db, I: InspectorExt> Deref for FoundryEvm<'db, I> { + type Target = Context; + + fn deref(&self) -> &Self::Target { + &self.inner.data.ctx + } +} + +impl DerefMut for FoundryEvm<'_, I> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.inner.data.ctx + } +} + +pub struct FoundryHandler<'db, I: InspectorExt> { + #[allow(clippy::type_complexity)] + inner: MainnetHandler< + RevmEvm< + EthEvmContext<&'db mut dyn DatabaseExt>, + I, + EthInstructions>, + FoundryPrecompiles, + >, + EVMError, + EthFrame< + RevmEvm< + EthEvmContext<&'db mut dyn DatabaseExt>, + I, + EthInstructions>, + FoundryPrecompiles, + >, + EVMError, + EthInterpreter, + >, + >, + create2_overrides: Vec<(usize, CallInputs)>, +} + +impl Default for FoundryHandler<'_, I> { + fn default() -> Self { + Self { inner: MainnetHandler::default(), create2_overrides: Vec::new() } + } +} + +impl<'db, I: InspectorExt> Handler for FoundryHandler<'db, I> { + type Evm = RevmEvm< + EthEvmContext<&'db mut dyn DatabaseExt>, + I, + EthInstructions>, + FoundryPrecompiles, + >; + type Error = EVMError; + type Frame = EthFrame< + RevmEvm< + EthEvmContext<&'db mut dyn DatabaseExt>, + I, + EthInstructions>, + FoundryPrecompiles, + >, + EVMError, + EthInterpreter, + >; + type HaltReason = HaltReason; + + fn frame_return_result( + &mut self, + frame: &mut Self::Frame, + evm: &mut Self::Evm, + result: ::FrameResult, + ) -> Result<(), Self::Error> { + let result = if self + .create2_overrides + .last() + .is_some_and(|(depth, _)| *depth == evm.journal().depth) + { + let (_, call_inputs) = self.create2_overrides.pop().unwrap(); + let FrameResult::Call(mut result) = result else { + unreachable!("create2 override should be a call frame"); + }; + + // Decode address from output. + let address = match result.instruction_result() { + return_ok!() => Address::try_from(result.output().as_ref()) + .map_err(|_| { + result.result = InterpreterResult { + result: InstructionResult::Revert, + output: "invalid CREATE2 factory output".into(), + gas: Gas::new(call_inputs.gas_limit), + }; + }) + .ok(), + _ => None, + }; + + FrameResult::Create(CreateOutcome { result: result.result, address }) + } else { + result + }; + + self.inner.frame_return_result(frame, evm, result) + } +} + +impl InspectorHandler for FoundryHandler<'_, I> { + type IT = EthInterpreter; + + fn inspect_frame_call( + &mut self, + frame: &mut Self::Frame, + evm: &mut Self::Evm, + ) -> Result, Self::Error> { + let frame_or_result = self.inner.inspect_frame_call(frame, evm)?; + + let ItemOrResult::Item(FrameInput::Create(inputs)) = &frame_or_result else { + return Ok(frame_or_result) + }; + + let CreateScheme::Create2 { salt } = inputs.scheme else { return Ok(frame_or_result) }; + + if !evm.data.inspector.should_use_create2_factory(&mut evm.data.ctx, inputs) { + return Ok(frame_or_result) + } + + let gas_limit = inputs.gas_limit; + + // Get CREATE2 deployer. + let create2_deployer = evm.data.inspector.create2_deployer(); + // Generate call inputs for CREATE2 factory. + let call_inputs = get_create2_factory_call_inputs(salt, inputs, create2_deployer); + + // Push data about current override to the stack. + self.create2_overrides.push((evm.journal().depth(), call_inputs.clone())); + + // Sanity check that CREATE2 deployer exists. + let code_hash = evm.journal().load_account(create2_deployer)?.info.code_hash; + if code_hash == KECCAK_EMPTY { + return Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome { + result: InterpreterResult { + result: InstructionResult::Revert, + output: format!("missing CREATE2 deployer: {create2_deployer}").into(), + gas: Gas::new(gas_limit), + }, + memory_offset: 0..0, + }))) + } else if code_hash != DEFAULT_CREATE2_DEPLOYER_CODEHASH { + return Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome { + result: InterpreterResult { + result: InstructionResult::Revert, + output: "invalid CREATE2 deployer bytecode".into(), + gas: Gas::new(gas_limit), + }, + memory_offset: 0..0, + }))) + } + + // Return the created CALL frame instead + Ok(ItemOrResult::Item(FrameInput::Call(Box::new(call_inputs)))) + } +} diff --git a/crates/evm/core/src/fork/database.rs b/crates/evm/core/src/fork/database.rs index 53595e451fd2f..30549f028aace 100644 --- a/crates/evm/core/src/fork/database.rs +++ b/crates/evm/core/src/fork/database.rs @@ -9,8 +9,9 @@ use alloy_rpc_types::BlockId; use foundry_fork_db::{BlockchainDb, DatabaseError, SharedBackend}; use parking_lot::Mutex; use revm::{ - db::{CacheDB, DatabaseRef}, - primitives::{Account, AccountInfo, Bytecode}, + bytecode::Bytecode, + database::{CacheDB, DatabaseRef}, + state::{Account, AccountInfo}, Database, DatabaseCommit, }; use std::sync::Arc; @@ -209,7 +210,12 @@ pub struct ForkDbStateSnapshot { impl ForkDbStateSnapshot { fn get_storage(&self, address: Address, index: U256) -> Option { - self.local.accounts.get(&address).and_then(|account| account.storage.get(&index)).copied() + self.local + .cache + .accounts + .get(&address) + .and_then(|account| account.storage.get(&index)) + .copied() } } @@ -220,7 +226,7 @@ impl DatabaseRef for ForkDbStateSnapshot { type Error = DatabaseError; fn basic_ref(&self, address: Address) -> Result, Self::Error> { - match self.local.accounts.get(&address) { + match self.local.cache.accounts.get(&address) { Some(account) => Ok(Some(account.info.clone())), None => { let mut acc = self.state_snapshot.accounts.get(&address).cloned(); @@ -238,7 +244,7 @@ impl DatabaseRef for ForkDbStateSnapshot { } fn storage_ref(&self, address: Address, index: U256) -> Result { - match self.local.accounts.get(&address) { + match self.local.cache.accounts.get(&address) { Some(account) => match account.storage.get(&index) { Some(entry) => Ok(*entry), None => match self.get_storage(address, index) { @@ -274,11 +280,7 @@ mod tests { async fn fork_db_insert_basic_default() { let rpc = foundry_test_utils::rpc::next_http_rpc_endpoint(); let provider = get_http_provider(rpc.clone()); - let meta = BlockchainDbMeta { - cfg_env: Default::default(), - block_env: Default::default(), - hosts: BTreeSet::from([rpc]), - }; + let meta = BlockchainDbMeta { block_env: Default::default(), hosts: BTreeSet::from([rpc]) }; let db = BlockchainDb::new(meta, None); let backend = SharedBackend::spawn_backend(Arc::new(provider), db.clone(), None).await; diff --git a/crates/evm/core/src/fork/init.rs b/crates/evm/core/src/fork/init.rs index c84cd945c4ded..8b23ae5b8531a 100644 --- a/crates/evm/core/src/fork/init.rs +++ b/crates/evm/core/src/fork/init.rs @@ -1,11 +1,11 @@ -use crate::utils::apply_chain_and_block_specific_env_changes; +use crate::{utils::apply_chain_and_block_specific_env_changes, AsEnvMut, Env, EvmEnv}; use alloy_consensus::BlockHeader; -use alloy_primitives::{Address, U256}; +use alloy_primitives::Address; use alloy_provider::{network::BlockResponse, Network, Provider}; use alloy_rpc_types::BlockNumberOrTag; use eyre::WrapErr; use foundry_common::NON_ARCHIVE_NODE_WARNING; -use revm::primitives::{BlockEnv, CfgEnv, Env, TxEnv}; +use revm::context::{BlockEnv, CfgEnv, TxEnv}; /// Initializes a REVM block environment based on a forked /// ethereum provider. @@ -46,38 +46,51 @@ pub async fn environment>( eyre::bail!("failed to get block for block number: {block_number}") }; - let mut cfg = CfgEnv::default(); - cfg.chain_id = override_chain_id.unwrap_or(rpc_chain_id); - cfg.memory_limit = memory_limit; - cfg.limit_contract_code_size = Some(usize::MAX); - // EIP-3607 rejects transactions from senders with deployed code. - // If EIP-3607 is enabled it can cause issues during fuzz/invariant tests if the caller - // is a contract. So we disable the check by default. - cfg.disable_eip3607 = true; - cfg.disable_block_gas_limit = disable_block_gas_limit; + let cfg = configure_env( + override_chain_id.unwrap_or(rpc_chain_id), + memory_limit, + disable_block_gas_limit, + ); let mut env = Env { - cfg, - block: BlockEnv { - number: U256::from(block.header().number()), - timestamp: U256::from(block.header().timestamp()), - coinbase: block.header().beneficiary(), - difficulty: block.header().difficulty(), - prevrandao: block.header().mix_hash(), - basefee: U256::from(block.header().base_fee_per_gas().unwrap_or_default()), - gas_limit: U256::from(block.header().gas_limit()), - ..Default::default() + evm_env: EvmEnv { + cfg_env: cfg, + block_env: BlockEnv { + number: block.header().number(), + timestamp: block.header().timestamp(), + beneficiary: block.header().beneficiary(), + difficulty: block.header().difficulty(), + prevrandao: block.header().mix_hash(), + basefee: block.header().base_fee_per_gas().unwrap_or_default(), + gas_limit: block.header().gas_limit(), + ..Default::default() + }, }, tx: TxEnv { caller: origin, - gas_price: U256::from(gas_price.unwrap_or(fork_gas_price)), + gas_price: gas_price.unwrap_or(fork_gas_price), chain_id: Some(override_chain_id.unwrap_or(rpc_chain_id)), gas_limit: block.header().gas_limit() as u64, ..Default::default() }, }; - apply_chain_and_block_specific_env_changes::(&mut env, &block); + apply_chain_and_block_specific_env_changes::(env.as_env_mut(), &block); Ok((env, block)) } + +/// Configures the environment for the given chain id and memory limit. +pub fn configure_env(chain_id: u64, memory_limit: u64, disable_block_gas_limit: bool) -> CfgEnv { + let mut cfg = CfgEnv::default(); + cfg.chain_id = chain_id; + cfg.memory_limit = memory_limit; + cfg.limit_contract_code_size = Some(usize::MAX); + // EIP-3607 rejects transactions from senders with deployed code. + // If EIP-3607 is enabled it can cause issues during fuzz/invariant tests if the caller + // is a contract. So we disable the check by default. + cfg.disable_eip3607 = true; + cfg.disable_block_gas_limit = disable_block_gas_limit; + cfg.disable_nonce_check = true; + cfg +} diff --git a/crates/evm/core/src/fork/mod.rs b/crates/evm/core/src/fork/mod.rs index 9401c2d32ed58..3049f9f957a63 100644 --- a/crates/evm/core/src/fork/mod.rs +++ b/crates/evm/core/src/fork/mod.rs @@ -1,8 +1,8 @@ use super::opts::EvmOpts; -use revm::primitives::Env; +use crate::Env; mod init; -pub use init::environment; +pub use init::{configure_env, environment}; pub mod database; diff --git a/crates/evm/core/src/fork/multi.rs b/crates/evm/core/src/fork/multi.rs index 2470c315410a2..59a05d67be2f2 100644 --- a/crates/evm/core/src/fork/multi.rs +++ b/crates/evm/core/src/fork/multi.rs @@ -4,8 +4,9 @@ //! concurrently active pairs at once. use super::CreateFork; +use crate::Env; use alloy_consensus::BlockHeader; -use alloy_primitives::{map::HashMap, U256}; +use alloy_primitives::map::HashMap; use alloy_provider::network::BlockResponse; use foundry_common::provider::{ProviderBuilder, RetryProvider}; use foundry_config::Config; @@ -16,7 +17,6 @@ use futures::{ task::{Context, Poll}, Future, FutureExt, StreamExt, }; -use revm::primitives::Env; use std::{ fmt::{self, Write}, pin::Pin, @@ -150,7 +150,7 @@ impl MultiFork { } /// Updates block number and timestamp of given fork with new values. - pub fn update_block(&self, fork: ForkId, number: U256, timestamp: U256) -> eyre::Result<()> { + pub fn update_block(&self, fork: ForkId, number: u64, timestamp: u64) -> eyre::Result<()> { trace!(?fork, ?number, ?timestamp, "update fork block"); self.handler .clone() @@ -200,7 +200,7 @@ enum Request { /// Returns the environment of the fork. GetEnv(ForkId, GetEnvSender), /// Updates the block number and timestamp of the fork. - UpdateBlock(ForkId, U256, U256), + UpdateBlock(ForkId, u64, u64), /// Shutdowns the entire `MultiForkHandler`, see `ShutDownMultiFork` ShutDown(OneshotSender<()>), /// Returns the Fork Url for the `ForkId` if it exists. @@ -302,10 +302,10 @@ impl MultiForkHandler { /// Update fork block number and timestamp. Used to preserve values set by `roll` and `warp` /// cheatcodes when new fork selected. - fn update_block(&mut self, fork_id: ForkId, block_number: U256, block_timestamp: U256) { + fn update_block(&mut self, fork_id: ForkId, block_number: u64, block_timestamp: u64) { if let Some(fork) = self.forks.get_mut(&fork_id) { - fork.opts.env.block.number = block_number; - fork.opts.env.block.timestamp = block_timestamp; + fork.opts.env.evm_env.block_env.number = block_number; + fork.opts.env.evm_env.block_env.timestamp = block_timestamp; } } @@ -519,7 +519,7 @@ async fn create_fork(mut fork: CreateFork) -> eyre::Result<(ForkId, CreatedFork, // Initialise the fork environment. let (env, block) = fork.evm_opts.fork_evm_env(&fork.url).await?; fork.env = env; - let meta = BlockchainDbMeta::new(fork.env.clone(), fork.url.clone()); + let meta = BlockchainDbMeta::new(fork.env.evm_env.block_env.clone(), fork.url.clone()); // We need to use the block number from the block because the env's number can be different on // some L2s (e.g. Arbitrum). @@ -527,7 +527,7 @@ async fn create_fork(mut fork: CreateFork) -> eyre::Result<(ForkId, CreatedFork, // Determine the cache path if caching is enabled. let cache_path = if fork.enable_caching { - Config::foundry_block_cache_dir(meta.cfg_env.chain_id, number) + Config::foundry_block_cache_dir(fork.env.evm_env.cfg_env.chain_id, number) } else { None }; diff --git a/crates/evm/core/src/ic.rs b/crates/evm/core/src/ic.rs index d58193dbefd03..7fc64791ace06 100644 --- a/crates/evm/core/src/ic.rs +++ b/crates/evm/core/src/ic.rs @@ -1,10 +1,6 @@ use alloy_primitives::map::rustc_hash::FxHashMap; use eyre::Result; -use revm::interpreter::{ - opcode::{PUSH0, PUSH1, PUSH32}, - OpCode, -}; -use revm_inspectors::opcode::immediate_size; +use revm::bytecode::opcode::{OpCode, PUSH0, PUSH1, PUSH32}; use serde::Serialize; /// Maps from program counter to instruction counter. @@ -117,8 +113,7 @@ pub fn decode_instructions(code: &[u8]) -> Result> { while pc < code.len() { let op = OpCode::new(code[pc]); let next_pc = pc + 1; - let immediate_size = - op.map(|op| immediate_size(op, &code[next_pc..])).unwrap_or(0) as usize; + let immediate_size = op.map(|op| op.info().immediate_size()).unwrap_or(0) as usize; let is_normal_push = op.map(|op| op.is_push()).unwrap_or(false); if !is_normal_push && next_pc + immediate_size > code.len() { @@ -138,3 +133,51 @@ pub fn decode_instructions(code: &[u8]) -> Result> { Ok(steps) } + +#[cfg(test)] +pub mod tests { + use super::*; + + #[test] + fn decode_push2_and_stop() -> Result<()> { + // 0x61 0xAA 0xBB = PUSH2 0xAABB + // 0x00 = STOP + let code = vec![0x61, 0xAA, 0xBB, 0x00]; + let insns = decode_instructions(&code)?; + + // PUSH2 then STOP + assert_eq!(insns.len(), 2); + + // PUSH2 at pc = 0 + let i0 = &insns[0]; + assert_eq!(i0.pc, 0); + assert_eq!(i0.op, Some(OpCode::PUSH2)); + assert_eq!(i0.immediate.as_ref(), &[0xAA, 0xBB]); + + // STOP at pc = 3 + let i1 = &insns[1]; + assert_eq!(i1.pc, 3); + assert_eq!(i1.op, Some(OpCode::STOP)); + assert!(i1.immediate.is_empty()); + + Ok(()) + } + + #[test] + fn decode_arithmetic_ops() -> Result<()> { + // 0x01 = ADD, 0x02 = MUL, 0x03 = SUB, 0x04 = DIV + let code = vec![0x01, 0x02, 0x03, 0x04]; + let insns = decode_instructions(&code)?; + + assert_eq!(insns.len(), 4); + + let expected = [(0, OpCode::ADD), (1, OpCode::MUL), (2, OpCode::SUB), (3, OpCode::DIV)]; + for ((pc, want_op), insn) in expected.iter().zip(insns.iter()) { + assert_eq!(insn.pc, *pc); + assert_eq!(insn.op, Some(*want_op)); + assert!(insn.immediate.is_empty()); + } + + Ok(()) + } +} diff --git a/crates/evm/core/src/lib.rs b/crates/evm/core/src/lib.rs index cf678551e21d6..76d6be35dd6cb 100644 --- a/crates/evm/core/src/lib.rs +++ b/crates/evm/core/src/lib.rs @@ -6,10 +6,11 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] use crate::constants::DEFAULT_CREATE2_DEPLOYER; +use alloy_evm::eth::EthEvmContext; use alloy_primitives::Address; use auto_impl::auto_impl; use backend::DatabaseExt; -use revm::{inspectors::NoOpInspector, interpreter::CreateInputs, EvmContext, Inspector}; +use revm::{inspector::NoOpInspector, interpreter::CreateInputs, Inspector}; use revm_inspectors::access_list::AccessListInspector; #[macro_use] @@ -20,13 +21,16 @@ pub mod abi { pub use foundry_evm_abi::*; } -mod ic; - +pub mod env; +pub use env::*; pub mod backend; pub mod buffer; pub mod constants; pub mod decode; +pub mod either_evm; +pub mod evm; pub mod fork; +pub mod ic; pub mod opcodes; pub mod opts; pub mod precompiles; @@ -36,15 +40,15 @@ pub mod utils; /// An extension trait that allows us to add additional hooks to Inspector for later use in /// handlers. #[auto_impl(&mut, Box)] -pub trait InspectorExt: for<'a> Inspector<&'a mut dyn DatabaseExt> { +pub trait InspectorExt: for<'a> Inspector> { /// Determines whether the `DEFAULT_CREATE2_DEPLOYER` should be used for a CREATE2 frame. /// /// If this function returns true, we'll replace CREATE2 frame with a CALL frame to CREATE2 /// factory. fn should_use_create2_factory( &mut self, - _context: &mut EvmContext<&mut dyn DatabaseExt>, - _inputs: &mut CreateInputs, + _context: &mut EthEvmContext<&mut dyn DatabaseExt>, + _inputs: &CreateInputs, ) -> bool { false } diff --git a/crates/evm/core/src/opcodes.rs b/crates/evm/core/src/opcodes.rs index 3251036c78f7a..7fad7ca5f3a3e 100644 --- a/crates/evm/core/src/opcodes.rs +++ b/crates/evm/core/src/opcodes.rs @@ -1,6 +1,6 @@ //! Opcode utils -use revm::interpreter::OpCode; +use revm::bytecode::opcode::OpCode; /// Returns true if the opcode modifies memory. /// diff --git a/crates/evm/core/src/opts.rs b/crates/evm/core/src/opts.rs index d135cceb904f9..11a602aab868f 100644 --- a/crates/evm/core/src/opts.rs +++ b/crates/evm/core/src/opts.rs @@ -1,11 +1,15 @@ use super::fork::environment; -use crate::{constants::DEFAULT_CREATE2_DEPLOYER, fork::CreateFork}; +use crate::{ + constants::DEFAULT_CREATE2_DEPLOYER, + fork::{configure_env, CreateFork}, + EvmEnv, +}; use alloy_primitives::{Address, B256, U256}; use alloy_provider::{network::AnyRpcBlock, Provider}; use eyre::WrapErr; use foundry_common::{provider::ProviderBuilder, ALCHEMY_FREE_TIER_CUPS}; use foundry_config::{Chain, Config, GasLimit}; -use revm::primitives::{BlockEnv, CfgEnv, TxEnv}; +use revm::context::{BlockEnv, TxEnv}; use serde::{Deserialize, Serialize}; use std::fmt::Write; use url::Url; @@ -106,7 +110,7 @@ impl EvmOpts { /// /// If a `fork_url` is set, it gets configured with settings fetched from the endpoint (chain /// id, ) - pub async fn evm_env(&self) -> eyre::Result { + pub async fn evm_env(&self) -> eyre::Result { if let Some(ref fork_url) = self.fork_url { Ok(self.fork_evm_env(fork_url).await?.0) } else { @@ -116,10 +120,7 @@ impl EvmOpts { /// Returns the `revm::Env` that is configured with settings retrieved from the endpoint. /// And the block that was used to configure the environment. - pub async fn fork_evm_env( - &self, - fork_url: &str, - ) -> eyre::Result<(revm::primitives::Env, AnyRpcBlock)> { + pub async fn fork_evm_env(&self, fork_url: &str) -> eyre::Result<(crate::Env, AnyRpcBlock)> { let provider = ProviderBuilder::new(fork_url) .compute_units_per_second(self.get_compute_units_per_second()) .build()?; @@ -145,31 +146,29 @@ impl EvmOpts { } /// Returns the `revm::Env` configured with only local settings - pub fn local_evm_env(&self) -> revm::primitives::Env { - let mut cfg = CfgEnv::default(); - cfg.chain_id = self.env.chain_id.unwrap_or(foundry_common::DEV_CHAIN_ID); - cfg.limit_contract_code_size = self.env.code_size_limit.or(Some(usize::MAX)); - cfg.memory_limit = self.memory_limit; - // EIP-3607 rejects transactions from senders with deployed code. - // If EIP-3607 is enabled it can cause issues during fuzz/invariant tests if the - // caller is a contract. So we disable the check by default. - cfg.disable_eip3607 = true; - cfg.disable_block_gas_limit = self.disable_block_gas_limit; - - revm::primitives::Env { - block: BlockEnv { - number: U256::from(self.env.block_number), - coinbase: self.env.block_coinbase, - timestamp: U256::from(self.env.block_timestamp), - difficulty: U256::from(self.env.block_difficulty), - prevrandao: Some(self.env.block_prevrandao), - basefee: U256::from(self.env.block_base_fee_per_gas), - gas_limit: U256::from(self.gas_limit()), - ..Default::default() + pub fn local_evm_env(&self) -> crate::Env { + let cfg = configure_env( + self.env.chain_id.unwrap_or(foundry_common::DEV_CHAIN_ID), + self.memory_limit, + self.disable_block_gas_limit, + ); + + crate::Env { + evm_env: EvmEnv { + cfg_env: cfg, + block_env: BlockEnv { + number: self.env.block_number, + beneficiary: self.env.block_coinbase, + timestamp: self.env.block_timestamp, + difficulty: U256::from(self.env.block_difficulty), + prevrandao: Some(self.env.block_prevrandao), + basefee: self.env.block_base_fee_per_gas, + gas_limit: self.gas_limit(), + ..Default::default() + }, }, - cfg, tx: TxEnv { - gas_price: U256::from(self.env.gas_price.unwrap_or_default()), + gas_price: self.env.gas_price.unwrap_or_default().into(), gas_limit: self.gas_limit(), caller: self.sender, ..Default::default() @@ -190,9 +189,9 @@ impl EvmOpts { /// /// for `mainnet` and `--fork-block-number 14435000` on mac the corresponding storage cache will /// be at `~/.foundry/cache/mainnet/14435000/storage.json`. - pub fn get_fork(&self, config: &Config, env: revm::primitives::Env) -> Option { + pub fn get_fork(&self, config: &Config, env: crate::Env) -> Option { let url = self.fork_url.clone()?; - let enable_caching = config.enable_caching(&url, env.cfg.chain_id); + let enable_caching = config.enable_caching(&url, env.evm_env.cfg_env.chain_id); Some(CreateFork { url, enable_caching, env, evm_opts: self.clone() }) } diff --git a/crates/evm/core/src/utils.rs b/crates/evm/core/src/utils.rs index 7125535694d49..fd11ee91654a0 100644 --- a/crates/evm/core/src/utils.rs +++ b/crates/evm/core/src/utils.rs @@ -1,5 +1,3 @@ -pub use crate::ic::*; -use crate::{backend::DatabaseExt, constants::DEFAULT_CREATE2_DEPLOYER_CODEHASH, InspectorExt}; use alloy_consensus::BlockHeader; use alloy_json_abi::{Function, JsonAbi}; use alloy_network::{AnyTxEnvelope, TransactionResponse}; @@ -8,20 +6,10 @@ use alloy_provider::{network::BlockResponse, Network}; use alloy_rpc_types::{Transaction, TransactionRequest}; use foundry_common::is_impersonated_tx; use foundry_config::NamedChain; -use foundry_fork_db::DatabaseError; -use revm::{ - handler::register::EvmHandler, - interpreter::{ - return_ok, CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, - Gas, InstructionResult, InterpreterResult, - }, - precompile::secp256r1::P256VERIFY, - primitives::{CreateScheme, EVMError, HandlerCfg, SpecId, KECCAK_EMPTY}, - FrameOrResult, FrameResult, -}; -use std::{cell::RefCell, rc::Rc, sync::Arc}; +use revm::primitives::hardfork::SpecId; +pub use revm::state::EvmState as StateChangeset; -pub use revm::primitives::EvmState as StateChangeset; +use crate::EnvMut; /// Depending on the configured chain id and block number this should apply any specific changes /// @@ -30,10 +18,11 @@ pub use revm::primitives::EvmState as StateChangeset; /// /// Should be called with proper chain id (retrieved from provider if not provided). pub fn apply_chain_and_block_specific_env_changes( - env: &mut revm::primitives::Env, + env: EnvMut<'_>, block: &N::BlockResponse, ) { use NamedChain::*; + if let Ok(chain) = NamedChain::try_from(env.cfg.chain_id) { let block_number = block.header().number(); @@ -72,7 +61,7 @@ pub fn apply_chain_and_block_specific_env_changes( serde_json::from_value::(l1_block_number).ok() }) { - env.block.number = l1_block_number; + env.block.number = l1_block_number.to(); } } _ => {} @@ -98,7 +87,7 @@ pub fn get_function<'a>( /// Configures the env for the given RPC transaction. /// Accounts for an impersonated transaction by resetting the `env.tx.caller` field to `tx.from`. -pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction) { +pub fn configure_tx_env(env: &mut EnvMut<'_>, tx: &Transaction) { let impersonated_from = is_impersonated_tx(&tx.inner).then_some(tx.from()); if let AnyTxEnvelope::Ethereum(tx) = &tx.inner.inner() { configure_tx_req_env(env, &tx.clone().into(), impersonated_from).expect("cannot fail"); @@ -109,7 +98,7 @@ pub fn configure_tx_env(env: &mut revm::primitives::Env, tx: &Transaction, tx: &TransactionRequest, impersonated_from: Option
, ) -> eyre::Result<()> { @@ -133,32 +122,31 @@ pub fn configure_tx_req_env( } = *tx; // If no `to` field then set create kind: https://eips.ethereum.org/EIPS/eip-2470#deployment-transaction - env.tx.transact_to = to.unwrap_or(TxKind::Create); + env.tx.kind = to.unwrap_or(TxKind::Create); // If the transaction is impersonated, we need to set the caller to the from // address Ref: https://github.com/foundry-rs/foundry/issues/9541 env.tx.caller = impersonated_from.unwrap_or(from.ok_or_else(|| eyre::eyre!("missing `from` field"))?); env.tx.gas_limit = gas.ok_or_else(|| eyre::eyre!("missing `gas` field"))?; - env.tx.nonce = nonce; + env.tx.nonce = nonce.unwrap_or_default(); env.tx.value = value.unwrap_or_default(); env.tx.data = input.input().cloned().unwrap_or_default(); env.tx.chain_id = chain_id; // Type 1, EIP-2930 - env.tx.access_list = access_list.clone().unwrap_or_default().0.into_iter().collect(); + env.tx.access_list = access_list.clone().unwrap_or_default(); // Type 2, EIP-1559 - env.tx.gas_price = U256::from(gas_price.or(max_fee_per_gas).unwrap_or_default()); - env.tx.gas_priority_fee = max_priority_fee_per_gas.map(U256::from); + env.tx.gas_price = gas_price.or(max_fee_per_gas).unwrap_or_default(); + env.tx.gas_priority_fee = max_priority_fee_per_gas; // Type 3, EIP-4844 env.tx.blob_hashes = blob_versioned_hashes.clone().unwrap_or_default(); - env.tx.max_fee_per_blob_gas = max_fee_per_blob_gas.map(U256::from); + env.tx.max_fee_per_blob_gas = max_fee_per_blob_gas.unwrap_or_default(); // Type 4, EIP-7702 if let Some(authorization_list) = authorization_list { - env.tx.authorization_list = - Some(revm::primitives::AuthorizationList::Signed(authorization_list.clone())); + env.tx.authorization_list = authorization_list.clone(); } Ok(()) @@ -166,202 +154,6 @@ pub fn configure_tx_req_env( /// Get the gas used, accounting for refunds pub fn gas_used(spec: SpecId, spent: u64, refunded: u64) -> u64 { - let refund_quotient = if SpecId::enabled(spec, SpecId::LONDON) { 5 } else { 2 }; + let refund_quotient = if SpecId::is_enabled_in(spec, SpecId::LONDON) { 5 } else { 2 }; spent - (refunded).min(spent / refund_quotient) } - -fn get_create2_factory_call_inputs( - salt: U256, - inputs: CreateInputs, - deployer: Address, -) -> CallInputs { - let calldata = [&salt.to_be_bytes::<32>()[..], &inputs.init_code[..]].concat(); - CallInputs { - caller: inputs.caller, - bytecode_address: deployer, - target_address: deployer, - scheme: CallScheme::Call, - value: CallValue::Transfer(inputs.value), - input: calldata.into(), - gas_limit: inputs.gas_limit, - is_static: false, - return_memory_offset: 0..0, - is_eof: false, - } -} - -/// Used for routing certain CREATE2 invocations through CREATE2_DEPLOYER. -/// -/// Overrides create hook with CALL frame if [InspectorExt::should_use_create2_factory] returns -/// true. Keeps track of overridden frames and handles outcome in the overridden insert_call_outcome -/// hook by inserting decoded address directly into interpreter. -/// -/// Should be installed after [revm::inspector_handle_register] and before any other registers. -pub fn create2_handler_register( - handler: &mut EvmHandler<'_, I, &mut dyn DatabaseExt>, -) { - let create2_overrides = Rc::>>::new(RefCell::new(Vec::new())); - - let create2_overrides_inner = create2_overrides.clone(); - let old_handle = handler.execution.create.clone(); - handler.execution.create = - Arc::new(move |ctx, mut inputs| -> Result> { - let CreateScheme::Create2 { salt } = inputs.scheme else { - return old_handle(ctx, inputs); - }; - if !ctx.external.should_use_create2_factory(&mut ctx.evm, &mut inputs) { - return old_handle(ctx, inputs); - } - - let gas_limit = inputs.gas_limit; - - // Get CREATE2 deployer. - let create2_deployer = ctx.external.create2_deployer(); - // Generate call inputs for CREATE2 factory. - let mut call_inputs = get_create2_factory_call_inputs(salt, *inputs, create2_deployer); - - // Call inspector to change input or return outcome. - let outcome = ctx.external.call(&mut ctx.evm, &mut call_inputs); - - // Push data about current override to the stack. - create2_overrides_inner - .borrow_mut() - .push((ctx.evm.journaled_state.depth(), call_inputs.clone())); - - // Sanity check that CREATE2 deployer exists. - let code_hash = ctx.evm.load_account(create2_deployer)?.info.code_hash; - if code_hash == KECCAK_EMPTY { - return Ok(FrameOrResult::Result(FrameResult::Call(CallOutcome { - result: InterpreterResult { - result: InstructionResult::Revert, - output: format!("missing CREATE2 deployer: {create2_deployer}").into(), - gas: Gas::new(gas_limit), - }, - memory_offset: 0..0, - }))) - } else if code_hash != DEFAULT_CREATE2_DEPLOYER_CODEHASH { - return Ok(FrameOrResult::Result(FrameResult::Call(CallOutcome { - result: InterpreterResult { - result: InstructionResult::Revert, - output: "invalid CREATE2 deployer bytecode".into(), - gas: Gas::new(gas_limit), - }, - memory_offset: 0..0, - }))) - } - - // Handle potential inspector override. - if let Some(outcome) = outcome { - return Ok(FrameOrResult::Result(FrameResult::Call(outcome))); - } - - // Create CALL frame for CREATE2 factory invocation. - let mut frame_or_result = ctx.evm.make_call_frame(&call_inputs); - - if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { - ctx.external - .initialize_interp(&mut frame.frame_data_mut().interpreter, &mut ctx.evm) - } - frame_or_result - }); - - let create2_overrides_inner = create2_overrides; - let old_handle = handler.execution.insert_call_outcome.clone(); - handler.execution.insert_call_outcome = - Arc::new(move |ctx, frame, shared_memory, mut outcome| { - // If we are on the depth of the latest override, handle the outcome. - if create2_overrides_inner - .borrow() - .last() - .is_some_and(|(depth, _)| *depth == ctx.evm.journaled_state.depth()) - { - let (_, call_inputs) = create2_overrides_inner.borrow_mut().pop().unwrap(); - outcome = ctx.external.call_end(&mut ctx.evm, &call_inputs, outcome); - - // Decode address from output. - let address = match outcome.instruction_result() { - return_ok!() => Address::try_from(outcome.output().as_ref()) - .map_err(|_| { - outcome.result = InterpreterResult { - result: InstructionResult::Revert, - output: "invalid CREATE2 factory output".into(), - gas: Gas::new(call_inputs.gas_limit), - }; - }) - .ok(), - _ => None, - }; - frame - .frame_data_mut() - .interpreter - .insert_create_outcome(CreateOutcome { address, result: outcome.result }); - - Ok(()) - } else { - old_handle(ctx, frame, shared_memory, outcome) - } - }); -} - -/// Adds Odyssey P256 precompile to the list of loaded precompiles. -pub fn odyssey_handler_register(handler: &mut EvmHandler<'_, EXT, DB>) { - let prev = handler.pre_execution.load_precompiles.clone(); - handler.pre_execution.load_precompiles = Arc::new(move || { - let mut loaded_precompiles = prev(); - - loaded_precompiles.extend([P256VERIFY]); - - loaded_precompiles - }); -} - -/// Creates a new EVM with the given inspector. -pub fn new_evm_with_inspector<'evm, 'i, 'db, I: InspectorExt + ?Sized>( - db: &'db mut dyn DatabaseExt, - env: revm::primitives::EnvWithHandlerCfg, - inspector: &'i mut I, -) -> revm::Evm<'evm, &'i mut I, &'db mut dyn DatabaseExt> { - let revm::primitives::EnvWithHandlerCfg { env, handler_cfg } = env; - - // NOTE: We could use `revm::Evm::builder()` here, but on the current patch it has some - // performance issues. - /* - revm::Evm::builder() - .with_db(db) - .with_env(env) - .with_external_context(inspector) - .with_handler_cfg(handler_cfg) - .append_handler_register(revm::inspector_handle_register) - .append_handler_register(create2_handler_register) - .build() - */ - - let mut handler = revm::Handler::new(handler_cfg); - handler.append_handler_register_plain(revm::inspector_handle_register); - if inspector.is_odyssey() { - handler.append_handler_register_plain(odyssey_handler_register); - } - handler.append_handler_register_plain(create2_handler_register); - - let context = revm::Context::new(revm::EvmContext::new_with_env(db, env), inspector); - - revm::Evm::new(context, handler) -} - -pub fn new_evm_with_existing_context<'a>( - inner: revm::InnerEvmContext<&'a mut dyn DatabaseExt>, - inspector: &'a mut dyn InspectorExt, -) -> revm::Evm<'a, &'a mut dyn InspectorExt, &'a mut dyn DatabaseExt> { - let handler_cfg = HandlerCfg::new(inner.spec_id()); - - let mut handler = revm::Handler::new(handler_cfg); - handler.append_handler_register_plain(revm::inspector_handle_register); - if inspector.is_odyssey() { - handler.append_handler_register_plain(odyssey_handler_register); - } - handler.append_handler_register_plain(create2_handler_register); - - let context = - revm::Context::new(revm::EvmContext { inner, precompiles: Default::default() }, inspector); - revm::Evm::new(context, handler) -} diff --git a/crates/evm/coverage/src/anchors.rs b/crates/evm/coverage/src/anchors.rs index 3d46065518c1b..415ad744b30e8 100644 --- a/crates/evm/coverage/src/anchors.rs +++ b/crates/evm/coverage/src/anchors.rs @@ -3,8 +3,8 @@ use crate::analysis::SourceAnalysis; use alloy_primitives::map::rustc_hash::FxHashSet; use eyre::ensure; use foundry_compilers::artifacts::sourcemap::{SourceElement, SourceMap}; -use foundry_evm_core::utils::IcPcMap; -use revm::interpreter::opcode; +use foundry_evm_core::ic::IcPcMap; +use revm::bytecode::opcode; /// Attempts to find anchors for the given items using the given source map and bytecode. pub fn find_anchors( diff --git a/crates/evm/coverage/src/inspector.rs b/crates/evm/coverage/src/inspector.rs index 6a6c50b093c8f..dfed9589e55fc 100644 --- a/crates/evm/coverage/src/inspector.rs +++ b/crates/evm/coverage/src/inspector.rs @@ -1,6 +1,11 @@ use crate::{HitMap, HitMaps}; use alloy_primitives::B256; -use revm::{interpreter::Interpreter, Database, EvmContext, Inspector}; +use revm::{ + context::ContextTr, + inspector::JournalExt, + interpreter::{interpreter_types::Jumps, Interpreter}, + Inspector, +}; use std::ptr::NonNull; /// Inspector implementation for collecting coverage information. @@ -29,16 +34,19 @@ impl Default for CoverageCollector { } } -impl Inspector for CoverageCollector { - fn initialize_interp(&mut self, interpreter: &mut Interpreter, _context: &mut EvmContext) { +impl Inspector for CoverageCollector +where + CTX: ContextTr, +{ + fn initialize_interp(&mut self, interpreter: &mut Interpreter, _context: &mut CTX) { get_or_insert_contract_hash(interpreter); self.insert_map(interpreter); } #[inline] - fn step(&mut self, interpreter: &mut Interpreter, _context: &mut EvmContext) { + fn step(&mut self, interpreter: &mut Interpreter, _context: &mut CTX) { let map = self.get_or_insert_map(interpreter); - map.hit(interpreter.program_counter() as u32); + map.hit(interpreter.bytecode.pc() as u32); } } @@ -64,14 +72,14 @@ impl CoverageCollector { #[cold] #[inline(never)] - fn insert_map(&mut self, interpreter: &Interpreter) { - let Some(hash) = interpreter.contract.hash else { eof_panic() }; + fn insert_map(&mut self, interpreter: &mut Interpreter) { + let hash = interpreter.bytecode.hash().unwrap_or_else(|| eof_panic()); self.current_hash = hash; // Converts the mutable reference to a `NonNull` pointer. self.current_map = self .maps .entry(hash) - .or_insert_with(|| HitMap::new(interpreter.contract.bytecode.original_bytes())) + .or_insert_with(|| HitMap::new(interpreter.bytecode.original_bytes())) .into(); } } @@ -81,18 +89,11 @@ impl CoverageCollector { /// If the contract hash is zero (contract not yet created but it's going to be created in current /// tx) then the hash is calculated from the bytecode. #[inline] -fn get_or_insert_contract_hash(interpreter: &mut Interpreter) -> &B256 { - let Some(hash) = interpreter.contract.hash.as_mut() else { eof_panic() }; - if hash.is_zero() { - set_contract_hash(hash, &interpreter.contract.bytecode); +fn get_or_insert_contract_hash(interpreter: &mut Interpreter) -> B256 { + if interpreter.bytecode.hash().is_none_or(|h| h.is_zero()) { + interpreter.bytecode.regenerate_hash(); } - hash -} - -#[cold] -#[inline(never)] -fn set_contract_hash(hash: &mut B256, bytecode: &revm::primitives::Bytecode) { - *hash = bytecode.hash_slow(); + interpreter.bytecode.hash().unwrap_or_else(|| eof_panic()) } #[cold] diff --git a/crates/evm/evm/Cargo.toml b/crates/evm/evm/Cargo.toml index 053a534405f7e..06074e305b630 100644 --- a/crates/evm/evm/Cargo.toml +++ b/crates/evm/evm/Cargo.toml @@ -24,6 +24,7 @@ foundry-evm-fuzz.workspace = true foundry-evm-traces.workspace = true alloy-dyn-abi = { workspace = true, features = ["arbitrary", "eip712"] } +alloy-evm.workspace = true alloy-json-abi.workspace = true alloy-primitives = { workspace = true, features = [ "serde", diff --git a/crates/evm/evm/src/executors/builder.rs b/crates/evm/evm/src/executors/builder.rs index c371a6550b879..a60934046efe1 100644 --- a/crates/evm/evm/src/executors/builder.rs +++ b/crates/evm/evm/src/executors/builder.rs @@ -1,6 +1,6 @@ use crate::{executors::Executor, inspectors::InspectorStackBuilder}; -use foundry_evm_core::backend::Backend; -use revm::primitives::{Env, EnvWithHandlerCfg, SpecId}; +use foundry_evm_core::{backend::Backend, Env}; +use revm::primitives::hardfork::SpecId; /// The builder that allows to configure an evm [`Executor`] which a stack of optional /// [`revm::Inspector`]s, such as [`Cheatcodes`]. @@ -27,7 +27,7 @@ impl Default for ExecutorBuilder { Self { stack: InspectorStackBuilder::new(), gas_limit: None, - spec_id: SpecId::LATEST, + spec_id: SpecId::default(), legacy_assertions: false, } } @@ -76,13 +76,18 @@ impl ExecutorBuilder { pub fn build(self, env: Env, db: Backend) -> Executor { let Self { mut stack, gas_limit, spec_id, legacy_assertions } = self; if stack.block.is_none() { - stack.block = Some(env.block.clone()); + stack.block = Some(env.evm_env.block_env.clone()); } if stack.gas_price.is_none() { stack.gas_price = Some(env.tx.gas_price); } - let gas_limit = gas_limit.unwrap_or_else(|| env.block.gas_limit.saturating_to()); - let env = EnvWithHandlerCfg::new_with_spec_id(Box::new(env), spec_id); + let gas_limit = gas_limit.unwrap_or(env.evm_env.block_env.gas_limit); + let env = Env::new_with_spec_id( + env.evm_env.cfg_env.clone(), + env.evm_env.block_env.clone(), + env.tx, + spec_id, + ); Executor::new(db, env, stack.build(), gas_limit, legacy_assertions) } } diff --git a/crates/evm/evm/src/executors/invariant/mod.rs b/crates/evm/evm/src/executors/invariant/mod.rs index 11c38bf43f29b..bf49f6c62f2ea 100644 --- a/crates/evm/evm/src/executors/invariant/mod.rs +++ b/crates/evm/evm/src/executors/invariant/mod.rs @@ -2,7 +2,7 @@ use crate::{ executors::{Executor, RawCallResult}, inspectors::Fuzzer, }; -use alloy_primitives::{Address, Bytes, FixedBytes, Selector, U256}; +use alloy_primitives::{map::HashMap, Address, Bytes, FixedBytes, Selector, U256}; use alloy_sol_types::{sol, SolCall}; use eyre::{eyre, ContextCompat, Result}; use foundry_common::contracts::{ContractsByAddress, ContractsByArtifact}; @@ -30,7 +30,7 @@ use proptest::{ test_runner::{TestCaseError, TestRunner}, }; use result::{assert_after_invariant, assert_invariants, can_continue}; -use revm::primitives::HashMap; +use revm::state::Account; use shrink::shrink_sequence; use std::{ cell::RefCell, @@ -865,7 +865,7 @@ impl<'a> InvariantExecutor<'a> { /// randomly generated addresses. fn collect_data( invariant_test: &InvariantTest, - state_changeset: &mut HashMap, + state_changeset: &mut HashMap, tx: &BasicTxDetails, call_result: &RawCallResult, run_depth: u32, diff --git a/crates/evm/evm/src/executors/invariant/replay.rs b/crates/evm/evm/src/executors/invariant/replay.rs index 89d7aa242a035..ab11f3728ae99 100644 --- a/crates/evm/evm/src/executors/invariant/replay.rs +++ b/crates/evm/evm/src/executors/invariant/replay.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::executors::Executor; use alloy_dyn_abi::JsonAbiExt; -use alloy_primitives::{map::HashMap, Log}; +use alloy_primitives::{map::HashMap, Log, U256}; use eyre::Result; use foundry_common::{ContractsByAddress, ContractsByArtifact}; use foundry_evm_coverage::HitMaps; @@ -16,7 +16,6 @@ use foundry_evm_traces::{load_contracts, TraceKind, TraceMode, Traces}; use indicatif::ProgressBar; use parking_lot::RwLock; use proptest::test_runner::TestError; -use revm::primitives::U256; use std::sync::Arc; /// Replays a call sequence for collecting logs and traces. diff --git a/crates/evm/evm/src/executors/mod.rs b/crates/evm/evm/src/executors/mod.rs index 5937912e17601..6ab4e3202967e 100644 --- a/crates/evm/evm/src/executors/mod.rs +++ b/crates/evm/evm/src/executors/mod.rs @@ -6,14 +6,17 @@ // `Executor` struct should be accessed using a trait defined in `foundry-evm-core` instead of // the concrete `Executor` type. -use crate::inspectors::{ - cheatcodes::BroadcastableTransactions, Cheatcodes, InspectorData, InspectorStack, +use crate::{ + inspectors::{ + cheatcodes::BroadcastableTransactions, Cheatcodes, InspectorData, InspectorStack, + }, + Env, }; use alloy_dyn_abi::{DynSolValue, FunctionExt, JsonAbiExt}; use alloy_json_abi::Function; use alloy_primitives::{ map::{AddressHashMap, HashMap}, - Address, Bytes, Log, U256, + Address, Bytes, Log, TxKind, U256, }; use alloy_sol_types::{sol, SolCall}; use foundry_evm_core::{ @@ -24,17 +27,20 @@ use foundry_evm_core::{ }, decode::{RevertDecoder, SkipReason}, utils::StateChangeset, - InspectorExt, + EvmEnv, InspectorExt, }; use foundry_evm_coverage::HitMaps; use foundry_evm_traces::{SparsedTraceArena, TraceMode}; use revm::{ - db::{DatabaseCommit, DatabaseRef}, - interpreter::{return_ok, InstructionResult}, - primitives::{ - AuthorizationList, BlockEnv, Bytecode, Env, EnvWithHandlerCfg, ExecutionResult, Output, - ResultAndState, SignedAuthorization, SpecId, TxEnv, TxKind, + bytecode::Bytecode, + context::{BlockEnv, TxEnv}, + context_interface::{ + result::{ExecutionResult, Output, ResultAndState}, + transaction::SignedAuthorization, }, + database::{DatabaseCommit, DatabaseRef}, + interpreter::{return_ok, InstructionResult}, + primitives::hardfork::SpecId, }; use std::{ borrow::Cow, @@ -83,7 +89,7 @@ pub struct Executor { // so the performance difference should be negligible. backend: Backend, /// The EVM environment. - env: EnvWithHandlerCfg, + env: Env, /// The Revm inspector stack. inspector: InspectorStack, /// The gas limit for calls and deployments. @@ -103,7 +109,7 @@ impl Executor { #[inline] pub fn new( mut backend: Backend, - env: EnvWithHandlerCfg, + env: Env, inspector: InspectorStack, gas_limit: u64, legacy_assertions: bool, @@ -112,7 +118,7 @@ impl Executor { // do not fail. backend.insert_account_info( CHEATCODE_ADDRESS, - revm::primitives::AccountInfo { + revm::state::AccountInfo { code: Some(Bytecode::new_raw(Bytes::from_static(&[0]))), // Also set the code hash manually so that it's not computed later. // The code hash value does not matter, as long as it's not zero or `KECCAK_EMPTY`. @@ -125,7 +131,12 @@ impl Executor { } fn clone_with_backend(&self, backend: Backend) -> Self { - let env = EnvWithHandlerCfg::new_with_spec_id(Box::new(self.env().clone()), self.spec_id()); + let env = Env::new_with_spec_id( + self.env.evm_env.cfg_env.clone(), + self.env.evm_env.block_env.clone(), + self.env.tx.clone(), + self.spec_id(), + ); Self::new(backend, env, self.inspector().clone(), self.gas_limit, self.legacy_assertions) } @@ -141,12 +152,12 @@ impl Executor { /// Returns a reference to the EVM environment. pub fn env(&self) -> &Env { - &self.env.env + &self.env } /// Returns a mutable reference to the EVM environment. pub fn env_mut(&mut self) -> &mut Env { - &mut self.env.env + &mut self.env } /// Returns a reference to the EVM inspector. @@ -161,12 +172,12 @@ impl Executor { /// Returns the EVM spec ID. pub fn spec_id(&self) -> SpecId { - self.env.spec_id() + self.env.evm_env.cfg_env.spec } /// Sets the EVM spec ID. pub fn set_spec_id(&mut self, spec_id: SpecId) { - self.env.handler_cfg.spec_id = spec_id; + self.env.evm_env.cfg_env.spec = spec_id; } /// Returns the gas limit for calls and deployments. @@ -238,6 +249,7 @@ impl Executor { let mut account = self.backend().basic_ref(address)?.unwrap_or_default(); account.nonce = nonce; self.backend_mut().insert_account_info(address, account); + self.env_mut().tx.nonce = nonce; Ok(()) } @@ -293,17 +305,17 @@ impl Executor { /// /// # Panics /// - /// Panics if `env.tx.transact_to` is not `TxKind::Create(_)`. + /// Panics if `env.tx.kind` is not `TxKind::Create(_)`. #[instrument(name = "deploy", level = "debug", skip_all)] pub fn deploy_with_env( &mut self, - env: EnvWithHandlerCfg, + env: Env, rd: Option<&RevertDecoder>, ) -> Result { assert!( - matches!(env.tx.transact_to, TxKind::Create), + matches!(env.tx.kind, TxKind::Create), "Expected create transaction, got {:?}", - env.tx.transact_to + env.tx.kind ); trace!(sender=%env.tx.caller, "deploying contract"); @@ -344,9 +356,9 @@ impl Executor { res = res.into_result(rd)?; // record any changes made to the block's environment during setup - self.env_mut().block = res.env.block.clone(); + self.env_mut().evm_env.block_env = res.env.evm_env.block_env.clone(); // and also the chainid, which can be set manually - self.env_mut().cfg.chain_id = res.env.cfg.chain_id; + self.env_mut().evm_env.cfg_env.chain_id = res.env.evm_env.cfg_env.chain_id; let success = self.is_raw_call_success(to, Cow::Borrowed(&res.state_changeset), &res, false); @@ -425,7 +437,8 @@ impl Executor { authorization_list: Vec, ) -> eyre::Result { let mut env = self.build_test_env(from, to.into(), calldata, value); - env.tx.authorization_list = Some(AuthorizationList::Signed(authorization_list)); + env.tx.authorization_list = authorization_list; + env.tx.tx_type = 4; self.call_with_env(env) } @@ -445,7 +458,7 @@ impl Executor { /// /// The state after the call is **not** persisted. #[instrument(name = "call", level = "debug", skip_all)] - pub fn call_with_env(&self, mut env: EnvWithHandlerCfg) -> eyre::Result { + pub fn call_with_env(&self, mut env: Env) -> eyre::Result { let mut inspector = self.inspector().clone(); let mut backend = CowBackend::new_borrowed(self.backend()); let result = backend.inspect(&mut env, &mut inspector)?; @@ -454,7 +467,7 @@ impl Executor { /// Execute the transaction configured in `env.tx`. #[instrument(name = "transact", level = "debug", skip_all)] - pub fn transact_with_env(&mut self, mut env: EnvWithHandlerCfg) -> eyre::Result { + pub fn transact_with_env(&mut self, mut env: Env) -> eyre::Result { let mut inspector = self.inspector().clone(); let backend = self.backend_mut(); let result = backend.inspect(&mut env, &mut inspector)?; @@ -631,37 +644,36 @@ impl Executor { /// /// If using a backend with cheatcodes, `tx.gas_price` and `block.number` will be overwritten by /// the cheatcode state in between calls. - fn build_test_env( - &self, - caller: Address, - transact_to: TxKind, - data: Bytes, - value: U256, - ) -> EnvWithHandlerCfg { - let env = Env { - cfg: self.env().cfg.clone(), - // We always set the gas price to 0 so we can execute the transaction regardless of - // 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::ZERO, - gas_limit: U256::from(self.gas_limit), - ..self.env().block.clone() + fn build_test_env(&self, caller: Address, kind: TxKind, data: Bytes, value: U256) -> Env { + Env { + evm_env: EvmEnv { + cfg_env: { + let mut cfg = self.env().evm_env.cfg_env.clone(); + cfg.spec = self.spec_id(); + cfg + }, + // We always set the gas price to 0 so we can execute the transaction regardless of + // network conditions - the actual gas price is kept in `self.block` and is applied + // by the cheatcode handler if it is enabled + block_env: BlockEnv { + basefee: 0, + gas_limit: self.gas_limit, + ..self.env().evm_env.block_env.clone() + }, }, tx: TxEnv { caller, - transact_to, + kind, data, value, // As above, we set the gas price to 0. - gas_price: U256::ZERO, + gas_price: 0, gas_priority_fee: None, gas_limit: self.gas_limit, + chain_id: Some(self.env().evm_env.cfg_env.chain_id), ..self.env().tx.clone() }, - }; - - EnvWithHandlerCfg::new_with_spec_id(Box::new(env), self.spec_id()) + } } pub fn call_sol_default(&self, to: Address, args: &C) -> C::Return @@ -797,7 +809,7 @@ pub struct RawCallResult { /// The changeset of the state. pub state_changeset: StateChangeset, /// The `revm::Env` after the call - pub env: EnvWithHandlerCfg, + pub env: Env, /// The cheatcode states after execution pub cheatcodes: Option, /// The raw output of the execution @@ -822,7 +834,7 @@ impl Default for RawCallResult { coverage: None, transactions: None, state_changeset: HashMap::default(), - env: EnvWithHandlerCfg::new_with_spec_id(Box::default(), SpecId::LATEST), + env: Env::default(), cheatcodes: Default::default(), out: None, chisel_state: None, @@ -920,7 +932,7 @@ impl std::ops::DerefMut for CallResult { /// Converts the data aggregated in the `inspector` and `call` to a `RawCallResult` fn convert_executed_result( - env: EnvWithHandlerCfg, + env: Env, inspector: InspectorStack, ResultAndState { result, state: state_changeset }: ResultAndState, has_state_snapshot_failure: bool, @@ -938,10 +950,11 @@ fn convert_executed_result( } }; let gas = revm::interpreter::gas::calculate_initial_tx_gas( - env.spec_id(), + env.evm_env.cfg_env.spec, &env.tx.data, - env.tx.transact_to.is_create(), - &env.tx.access_list, + env.tx.kind.is_create(), + env.tx.access_list.len().try_into()?, + 0, 0, ); diff --git a/crates/evm/evm/src/executors/trace.rs b/crates/evm/evm/src/executors/trace.rs index 026612c88c484..c58ee8ddd6e59 100644 --- a/crates/evm/evm/src/executors/trace.rs +++ b/crates/evm/evm/src/executors/trace.rs @@ -1,10 +1,13 @@ -use crate::executors::{Executor, ExecutorBuilder}; +use crate::{ + executors::{Executor, ExecutorBuilder}, + Env, +}; use alloy_primitives::Address; use foundry_compilers::artifacts::EvmVersion; use foundry_config::{utils::evm_spec_id, Chain, Config}; use foundry_evm_core::{backend::Backend, fork::CreateFork, opts::EvmOpts}; use foundry_evm_traces::TraceMode; -use revm::primitives::{Env, SpecId}; +use revm::primitives::hardfork::SpecId; use std::ops::{Deref, DerefMut}; /// A default executor with tracing enabled @@ -14,7 +17,7 @@ pub struct TracingExecutor { impl TracingExecutor { pub fn new( - env: revm::primitives::Env, + env: Env, fork: Option, version: Option, trace_mode: TraceMode, diff --git a/crates/evm/evm/src/inspectors/chisel_state.rs b/crates/evm/evm/src/inspectors/chisel_state.rs index 023389ed4dfff..33798e7b0c6a4 100644 --- a/crates/evm/evm/src/inspectors/chisel_state.rs +++ b/crates/evm/evm/src/inspectors/chisel_state.rs @@ -1,7 +1,12 @@ use alloy_primitives::U256; +use foundry_evm_core::backend::DatabaseError; use revm::{ - interpreter::{InstructionResult, Interpreter}, - Database, EvmContext, Inspector, + context::ContextTr, + inspector::JournalExt, + interpreter::{ + interpreter::EthInterpreter, interpreter_types::Jumps, InstructionResult, Interpreter, + }, + Database, Inspector, }; /// An inspector for Chisel @@ -21,16 +26,21 @@ impl ChiselState { } } -impl Inspector for ChiselState { +impl Inspector for ChiselState +where + D: Database, + CTX: ContextTr, + CTX::Journal: JournalExt, +{ #[cold] - fn step_end(&mut self, interp: &mut Interpreter, _context: &mut EvmContext) { + fn step_end(&mut self, interp: &mut Interpreter, _context: &mut CTX) { // If we are at the final pc of the REPL contract execution, set the state. // Subtraction can't overflow because `pc` is always at least 1 in `step_end`. - if self.final_pc == interp.program_counter() - 1 { + if self.final_pc == interp.bytecode.pc() - 1 { self.state = Some(( interp.stack.data().clone(), - interp.shared_memory.context_memory().to_vec(), - interp.instruction_result, + interp.memory.borrow().context_memory().to_vec(), + interp.control.instruction_result, )) } } diff --git a/crates/evm/evm/src/inspectors/custom_printer.rs b/crates/evm/evm/src/inspectors/custom_printer.rs new file mode 100644 index 0000000000000..a35958ee550d0 --- /dev/null +++ b/crates/evm/evm/src/inspectors/custom_printer.rs @@ -0,0 +1,114 @@ +//! Custom print inspector, it has step level information of execution. +//! It is a great tool if some debugging is needed. + +use foundry_common::sh_println; +use foundry_evm_core::backend::DatabaseError; +use revm::{ + bytecode::opcode::OpCode, + context::{ContextTr, JournalTr}, + inspector::{inspectors::GasInspector, JournalExt}, + interpreter::{ + interpreter::EthInterpreter, + interpreter_types::{Jumps, LoopControl, MemoryTr}, + CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, + }, + primitives::{Address, U256}, + Database, Inspector, +}; + +/// Custom print [Inspector], it has step level information of execution. +/// +/// It is a great tool if some debugging is needed. +#[derive(Clone, Debug, Default)] +pub struct CustomPrintTracer { + gas_inspector: GasInspector, +} + +impl Inspector for CustomPrintTracer +where + D: Database, + CTX: ContextTr, + CTX::Journal: JournalExt, +{ + fn initialize_interp(&mut self, interp: &mut Interpreter, _context: &mut CTX) { + self.gas_inspector.initialize_interp(&interp.control.gas); + } + + // get opcode by calling `interp.contract.opcode(interp.program_counter())`. + // all other information can be obtained from interp. + fn step(&mut self, interp: &mut Interpreter, context: &mut CTX) { + let opcode = interp.bytecode.opcode(); + let name = OpCode::name_by_op(opcode); + + let gas_remaining = self.gas_inspector.gas_remaining(); + + let memory_size = interp.memory.size(); + + let _ = sh_println!( + "depth:{}, PC:{}, gas:{:#x}({}), OPCODE: {:?}({:?}) refund:{:#x}({}) Stack:{:?}, Data size:{}", + context.journal().depth(), + interp.bytecode.pc(), + gas_remaining, + gas_remaining, + name, + opcode, + interp.control.gas.refunded(), + interp.control.gas.refunded(), + interp.stack.data(), + memory_size, + ); + + self.gas_inspector.step(&interp.control.gas); + } + + fn step_end(&mut self, interp: &mut Interpreter, _context: &mut CTX) { + self.gas_inspector.step_end(interp.control.gas_mut()); + } + + fn call_end(&mut self, _context: &mut CTX, _inputs: &CallInputs, outcome: &mut CallOutcome) { + self.gas_inspector.call_end(outcome) + } + + fn create_end( + &mut self, + _context: &mut CTX, + _inputs: &CreateInputs, + outcome: &mut CreateOutcome, + ) { + self.gas_inspector.create_end(outcome) + } + + fn call(&mut self, _context: &mut CTX, inputs: &mut CallInputs) -> Option { + let _ = sh_println!( + "SM Address: {:?}, caller:{:?},target:{:?} is_static:{:?}, transfer:{:?}, input_size:{:?}", + inputs.bytecode_address, + inputs.caller, + inputs.target_address, + inputs.is_static, + inputs.value, + inputs.input.len(), + ); + None + } + + fn create(&mut self, _context: &mut CTX, inputs: &mut CreateInputs) -> Option { + let _ = sh_println!( + "CREATE CALL: caller:{:?}, scheme:{:?}, value:{:?}, init_code:{:?}, gas:{:?}", + inputs.caller, + inputs.scheme, + inputs.value, + inputs.init_code, + inputs.gas_limit + ); + None + } + + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + let _ = sh_println!( + "SELFDESTRUCT: contract: {:?}, refund target: {:?}, value {:?}", + contract, + target, + value + ); + } +} diff --git a/crates/evm/evm/src/inspectors/logs.rs b/crates/evm/evm/src/inspectors/logs.rs index 570fb47dbe238..d6aed69892b60 100644 --- a/crates/evm/evm/src/inspectors/logs.rs +++ b/crates/evm/evm/src/inspectors/logs.rs @@ -1,12 +1,17 @@ use alloy_primitives::Log; use alloy_sol_types::{SolEvent, SolInterface, SolValue}; use foundry_common::{fmt::ConsoleFmt, ErrorExt}; -use foundry_evm_core::{abi::console, constants::HARDHAT_CONSOLE_ADDRESS, InspectorExt}; +use foundry_evm_core::{ + abi::console, backend::DatabaseError, constants::HARDHAT_CONSOLE_ADDRESS, InspectorExt, +}; use revm::{ + context::ContextTr, + inspector::JournalExt, interpreter::{ - CallInputs, CallOutcome, Gas, InstructionResult, Interpreter, InterpreterResult, + interpreter::EthInterpreter, CallInputs, CallOutcome, Gas, InstructionResult, Interpreter, + InterpreterResult, }, - Database, EvmContext, Inspector, + Database, Inspector, }; /// An inspector that collects logs during execution. @@ -39,16 +44,17 @@ impl LogCollector { } } -impl Inspector for LogCollector { - fn log(&mut self, _interp: &mut Interpreter, _context: &mut EvmContext, log: &Log) { - self.logs.push(log.clone()); +impl Inspector for LogCollector +where + D: Database, + CTX: ContextTr, + CTX::Journal: JournalExt, +{ + fn log(&mut self, _interp: &mut Interpreter, _context: &mut CTX, log: Log) { + self.logs.push(log); } - fn call( - &mut self, - _context: &mut EvmContext, - inputs: &mut CallInputs, - ) -> Option { + fn call(&mut self, _context: &mut CTX, inputs: &mut CallInputs) -> Option { if inputs.target_address == HARDHAT_CONSOLE_ADDRESS { return self.do_hardhat_log(inputs); } diff --git a/crates/evm/evm/src/inspectors/mod.rs b/crates/evm/evm/src/inspectors/mod.rs index 914bf460e5e44..fcf6836e2b9d8 100644 --- a/crates/evm/evm/src/inspectors/mod.rs +++ b/crates/evm/evm/src/inspectors/mod.rs @@ -7,6 +7,9 @@ pub use foundry_evm_traces::{StackSnapshotType, TracingInspector, TracingInspect pub use revm_inspectors::access_list::AccessListInspector; +mod custom_printer; +pub use custom_printer::CustomPrintTracer; + mod chisel_state; pub use chisel_state::ChiselState; diff --git a/crates/evm/evm/src/inspectors/script.rs b/crates/evm/evm/src/inspectors/script.rs index 57fa7b209b162..205215f08db08 100644 --- a/crates/evm/evm/src/inspectors/script.rs +++ b/crates/evm/evm/src/inspectors/script.rs @@ -1,8 +1,15 @@ +use alloy_evm::Database; use alloy_primitives::Address; use foundry_common::sh_err; +use foundry_evm_core::backend::DatabaseError; use revm::{ - interpreter::{opcode::ADDRESS, InstructionResult, Interpreter}, - Database, EvmContext, Inspector, + bytecode::opcode::ADDRESS, + context::ContextTr, + inspector::JournalExt, + interpreter::{ + interpreter::EthInterpreter, interpreter_types::Jumps, InstructionResult, Interpreter, + }, + Inspector, }; /// An inspector that enforces certain rules during script execution. @@ -14,21 +21,26 @@ pub struct ScriptExecutionInspector { pub script_address: Address, } -impl Inspector for ScriptExecutionInspector { +impl Inspector for ScriptExecutionInspector +where + D: Database, + CTX: ContextTr, + CTX::Journal: JournalExt, +{ #[inline] - fn step(&mut self, interpreter: &mut Interpreter, _ecx: &mut EvmContext) { + fn step(&mut self, interpreter: &mut Interpreter, _ecx: &mut CTX) { // Check if both target and bytecode address are the same as script contract address // (allow calling external libraries when bytecode address is different). - if interpreter.current_opcode() == ADDRESS && - interpreter.contract.target_address == self.script_address && - interpreter.contract.bytecode_address.unwrap_or_default() == self.script_address + if interpreter.bytecode.opcode() == ADDRESS && + interpreter.input.target_address == self.script_address && + interpreter.input.bytecode_address == Some(self.script_address) { // Log the reason for revert let _ = sh_err!( "Usage of `address(this)` detected in script contract. Script contracts are ephemeral and their addresses should not be relied upon." ); // Set the instruction result to Revert to stop execution - interpreter.instruction_result = InstructionResult::Revert; + interpreter.control.instruction_result = InstructionResult::Revert; } // Note: We don't return anything here as step returns void. // The original check returned InstructionResult::Continue, but that's the default diff --git a/crates/evm/evm/src/inspectors/stack.rs b/crates/evm/evm/src/inspectors/stack.rs index 773730d6cc136..a4bf2930c7fec 100644 --- a/crates/evm/evm/src/inspectors/stack.rs +++ b/crates/evm/evm/src/inspectors/stack.rs @@ -1,23 +1,32 @@ use super::{ - Cheatcodes, CheatsConfig, ChiselState, CoverageCollector, Fuzzer, LogCollector, - ScriptExecutionInspector, TracingInspector, + Cheatcodes, CheatsConfig, ChiselState, CoverageCollector, CustomPrintTracer, Fuzzer, + LogCollector, ScriptExecutionInspector, TracingInspector, +}; +use alloy_evm::{eth::EthEvmContext, Evm}; +use alloy_primitives::{ + map::{AddressHashMap, HashMap}, + Address, Bytes, Log, TxKind, U256, }; -use alloy_primitives::{map::AddressHashMap, Address, Bytes, Log, TxKind, U256}; use foundry_cheatcodes::{CheatcodesExecutor, Wallets}; -use foundry_evm_core::{backend::DatabaseExt, InspectorExt}; +use foundry_evm_core::{ + backend::{DatabaseExt, JournaledState}, + evm::new_evm_with_inspector, + ContextExt, Env, InspectorExt, +}; use foundry_evm_coverage::HitMaps; use foundry_evm_traces::{SparsedTraceArena, TraceMode}; use revm::{ - inspectors::CustomPrintTracer, + context::{ + result::{ExecutionResult, Output}, + BlockEnv, + }, + context_interface::CreateScheme, interpreter::{ CallInputs, CallOutcome, CallScheme, CreateInputs, CreateOutcome, EOFCreateInputs, EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, }, - primitives::{ - Account, AccountStatus, BlockEnv, CreateScheme, Env, EnvWithHandlerCfg, ExecutionResult, - HashMap, Output, TransactTo, - }, - EvmContext, Inspector, JournaledState, + state::{Account, AccountStatus}, + Inspector, }; use std::{ ops::{Deref, DerefMut}, @@ -36,7 +45,7 @@ pub struct InspectorStackBuilder { /// /// Used in the cheatcode handler to overwrite the gas price separately from the gas price /// in the execution environment. - pub gas_price: Option, + pub gas_price: Option, /// The cheatcodes config. pub cheatcodes: Option>, /// The fuzzer inspector and its state, if it exists. @@ -79,7 +88,7 @@ impl InspectorStackBuilder { /// Set the gas price. #[inline] - pub fn gas_price(mut self, gas_price: U256) -> Self { + pub fn gas_price(mut self, gas_price: u128) -> Self { self.gas_price = Some(gas_price); self } @@ -232,7 +241,7 @@ macro_rules! call_inspectors { } )+ }; - (#[ret] [$($inspector:expr),+ $(,)?], |$id:ident $(,)?| $call:expr $(,)?) => { + (#[ret] [$($inspector:expr),+ $(,)?], |$id:ident $(,)?| $call:expr $(,)?) => {{ $( if let Some($id) = $inspector { if let Some(result) = ({ #[inline(always)] #[cold] || $call })() { @@ -240,7 +249,7 @@ macro_rules! call_inspectors { } } )+ - }; + }}; } /// The collected results of [`InspectorStack`]. @@ -355,7 +364,7 @@ impl InspectorStack { /// Set variables from an environment for the relevant inspectors. #[inline] pub fn set_env(&mut self, env: &Env) { - self.set_block(&env.block); + self.set_block(&env.evm_env.block_env); self.set_gas_price(env.tx.gas_price); } @@ -369,7 +378,7 @@ impl InspectorStack { /// Sets the gas price for the relevant inspectors. #[inline] - pub fn set_gas_price(&mut self, gas_price: U256) { + pub fn set_gas_price(&mut self, gas_price: u128) { if let Some(cheatcodes) = &mut self.cheatcodes { cheatcodes.gas_price = Some(gas_price); } @@ -496,128 +505,129 @@ impl InspectorStackRefMut<'_> { /// Should be called on the top-level call of inner context (depth == 0 && /// self.in_inner_context) Decreases sender nonce for CALLs to keep backwards compatibility /// Updates tx.origin to the value before entering inner context - fn adjust_evm_data_for_inner_context(&mut self, ecx: &mut EvmContext<&mut dyn DatabaseExt>) { + fn adjust_evm_data_for_inner_context(&mut self, ecx: &mut EthEvmContext<&mut dyn DatabaseExt>) { let inner_context_data = self.inner_context_data.as_ref().expect("should be called in inner context"); - ecx.env.tx.caller = inner_context_data.original_origin; + ecx.tx.caller = inner_context_data.original_origin; } fn do_call_end( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, inputs: &CallInputs, - outcome: CallOutcome, + outcome: &mut CallOutcome, ) -> CallOutcome { let result = outcome.result.result; call_inspectors!( #[ret] [&mut self.fuzzer, &mut self.tracer, &mut self.cheatcodes, &mut self.printer], |inspector| { - let new_outcome = inspector.call_end(ecx, inputs, outcome.clone()); + let previous_outcome = outcome.clone(); + inspector.call_end(ecx, inputs, outcome); // If the inspector returns a different status or a revert with a non-empty message, // we assume it wants to tell us something - let different = new_outcome.result.result != result || - (new_outcome.result.result == InstructionResult::Revert && - new_outcome.output() != outcome.output()); - different.then_some(new_outcome) + let different = outcome.result.result != result || + (outcome.result.result == InstructionResult::Revert && + outcome.output() != previous_outcome.output()); + different.then_some(outcome.clone()) }, ); - outcome + outcome.clone() } fn do_create_end( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, call: &CreateInputs, - outcome: CreateOutcome, + outcome: &mut CreateOutcome, ) -> CreateOutcome { let result = outcome.result.result; call_inspectors!( #[ret] [&mut self.tracer, &mut self.cheatcodes, &mut self.printer], |inspector| { - let new_outcome = inspector.create_end(ecx, call, outcome.clone()); + let previous_outcome = outcome.clone(); + inspector.create_end(ecx, call, outcome); // If the inspector returns a different status or a revert with a non-empty message, // we assume it wants to tell us something - let different = new_outcome.result.result != result || - (new_outcome.result.result == InstructionResult::Revert && - new_outcome.output() != outcome.output()); - different.then_some(new_outcome) + let different = outcome.result.result != result || + (outcome.result.result == InstructionResult::Revert && + outcome.output() != previous_outcome.output()); + different.then_some(outcome.clone()) }, ); - outcome + outcome.clone() } fn do_eofcreate_end( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, call: &EOFCreateInputs, - outcome: CreateOutcome, + outcome: &mut CreateOutcome, ) -> CreateOutcome { let result = outcome.result.result; call_inspectors!( #[ret] [&mut self.tracer, &mut self.cheatcodes, &mut self.printer], |inspector| { - let new_outcome = inspector.eofcreate_end(ecx, call, outcome.clone()); + let previous_outcome = outcome.clone(); + inspector.eofcreate_end(ecx, call, outcome); // If the inspector returns a different status or a revert with a non-empty message, // we assume it wants to tell us something - let different = new_outcome.result.result != result || - (new_outcome.result.result == InstructionResult::Revert && - new_outcome.output() != outcome.output()); - different.then_some(new_outcome) + let different = outcome.result.result != result || + (outcome.result.result == InstructionResult::Revert && + outcome.output() != previous_outcome.output()); + different.then_some(outcome.clone()) }, ); - outcome + outcome.clone() } fn transact_inner( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, - transact_to: TransactTo, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, + kind: TxKind, caller: Address, input: Bytes, gas_limit: u64, value: U256, ) -> (InterpreterResult, Option
) { - let ecx = &mut ecx.inner; + let cached_env = Env::from(ecx.cfg.clone(), ecx.block.clone(), ecx.tx.clone()); - let cached_env = ecx.env.clone(); - - ecx.env.block.basefee = U256::ZERO; - ecx.env.tx.caller = caller; - ecx.env.tx.transact_to = transact_to; - ecx.env.tx.data = input; - ecx.env.tx.value = value; + ecx.block.basefee = 0; + ecx.tx.caller = caller; + ecx.tx.kind = kind; + ecx.tx.data = input; + ecx.tx.value = value; // Add 21000 to the gas limit to account for the base cost of transaction. - ecx.env.tx.gas_limit = gas_limit + 21000; + ecx.tx.gas_limit = gas_limit + 21000; + // If we haven't disabled gas limit checks, ensure that transaction gas limit will not // exceed block gas limit. - if !ecx.env.cfg.disable_block_gas_limit { - ecx.env.tx.gas_limit = - std::cmp::min(ecx.env.tx.gas_limit, ecx.env.block.gas_limit.to()); + if !ecx.cfg.disable_block_gas_limit { + ecx.tx.gas_limit = std::cmp::min(ecx.tx.gas_limit, ecx.block.gas_limit); } - ecx.env.tx.gas_price = U256::ZERO; + ecx.tx.gas_price = 0; self.inner_context_data = Some(InnerContextData { original_origin: cached_env.tx.caller }); self.in_inner_context = true; - let env = EnvWithHandlerCfg::new_with_spec_id(ecx.env.clone(), ecx.spec_id()); let res = self.with_stack(|inspector| { - let mut evm = crate::utils::new_evm_with_inspector(&mut ecx.db, env, inspector); + let (db, journal, env) = ecx.as_db_env_and_journal(); + let mut evm = new_evm_with_inspector(db, env.to_owned(), inspector); - evm.context.evm.inner.journaled_state.state = { - let mut state = ecx.journaled_state.state.clone(); + evm.journaled_state.state = { + let mut state = journal.state.clone(); for (addr, acc_mut) in &mut state { // mark all accounts cold, besides preloaded addresses - if !ecx.journaled_state.warm_preloaded_addresses.contains(addr) { + if !journal.warm_preloaded_addresses.contains(addr) { acc_mut.mark_cold(); } @@ -632,21 +642,23 @@ impl InspectorStackRefMut<'_> { }; // set depth to 1 to make sure traces are collected correctly - evm.context.evm.inner.journaled_state.depth = 1; + evm.journaled_state.depth = 1; - let res = evm.transact(); + let res = evm.transact(env.tx.clone()); // need to reset the env in case it was modified via cheatcodes during execution - ecx.env = evm.context.evm.inner.env; + *env.cfg = evm.cfg.clone(); + *env.block = evm.block.clone(); + + *env.tx = cached_env.tx; + env.block.basefee = cached_env.evm_env.block_env.basefee; + res }); self.in_inner_context = false; self.inner_context_data = None; - ecx.env.tx = cached_env.tx; - ecx.env.block.basefee = cached_env.block.basefee; - let mut gas = Gas::new(gas_limit); let Ok(res) = res else { @@ -726,7 +738,7 @@ impl InspectorStackRefMut<'_> { } /// Invoked at the beginning of a new top-level (0 depth) frame. - fn top_level_frame_start(&mut self, ecx: &mut EvmContext<&mut dyn DatabaseExt>) { + fn top_level_frame_start(&mut self, ecx: &mut EthEvmContext<&mut dyn DatabaseExt>) { if self.enable_isolation { // If we're in isolation mode, we need to keep track of the state at the beginning of // the frame to be able to roll back on revert @@ -737,7 +749,7 @@ impl InspectorStackRefMut<'_> { /// Invoked at the end of root frame. fn top_level_frame_end( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, result: InstructionResult, ) { if !result.is_revert() { @@ -759,11 +771,11 @@ impl InspectorStackRefMut<'_> { } } -impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { +impl Inspector> for InspectorStackRefMut<'_> { fn initialize_interp( &mut self, interpreter: &mut Interpreter, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, ) { call_inspectors!( [ @@ -777,7 +789,11 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { ); } - fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext<&mut dyn DatabaseExt>) { + fn step( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, + ) { call_inspectors!( [ &mut self.fuzzer, @@ -794,7 +810,7 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { fn step_end( &mut self, interpreter: &mut Interpreter, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, ) { call_inspectors!( [&mut self.tracer, &mut self.cheatcodes, &mut self.chisel_state, &mut self.printer], @@ -805,18 +821,18 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { fn log( &mut self, interpreter: &mut Interpreter, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, - log: &Log, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, + log: Log, ) { call_inspectors!( [&mut self.tracer, &mut self.log_collector, &mut self.cheatcodes, &mut self.printer], - |inspector| inspector.log(interpreter, ecx, log), + |inspector| inspector.log(interpreter, ecx, log.clone()), ); } fn call( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, call: &mut CallInputs, ) -> Option { if self.in_inner_context && ecx.journaled_state.depth == 1 { @@ -882,7 +898,7 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { // Mark accounts and storage cold before STATICCALLs CallScheme::StaticCall | CallScheme::ExtStaticCall => { let JournaledState { state, warm_preloaded_addresses, .. } = - &mut ecx.journaled_state; + &mut ecx.journaled_state.inner; for (addr, acc_mut) in state { // Do not mark accounts and storage cold accounts with arbitrary storage. if let Some(cheatcodes) = &self.cheatcodes { @@ -910,28 +926,26 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { fn call_end( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, inputs: &CallInputs, - outcome: CallOutcome, - ) -> CallOutcome { + outcome: &mut CallOutcome, + ) { // We are processing inner context outputs in the outer context, so need to avoid processing // twice. if self.in_inner_context && ecx.journaled_state.depth == 1 { - return outcome; + return; } - let outcome = self.do_call_end(ecx, inputs, outcome); + self.do_call_end(ecx, inputs, outcome); if ecx.journaled_state.depth == 0 { self.top_level_frame_end(ecx, outcome.result.result); } - - outcome } fn create( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, create: &mut CreateInputs, ) -> Option { if self.in_inner_context && ecx.journaled_state.depth == 1 { @@ -970,28 +984,26 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { fn create_end( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, call: &CreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + outcome: &mut CreateOutcome, + ) { // We are processing inner context outputs in the outer context, so need to avoid processing // twice. if self.in_inner_context && ecx.journaled_state.depth == 1 { - return outcome; + return; } - let outcome = self.do_create_end(ecx, call, outcome); + self.do_create_end(ecx, call, outcome); if ecx.journaled_state.depth == 0 { self.top_level_frame_end(ecx, outcome.result.result); } - - outcome } fn eofcreate( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, create: &mut EOFCreateInputs, ) -> Option { if self.in_inner_context && ecx.journaled_state.depth == 1 { @@ -1035,28 +1047,28 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { fn eofcreate_end( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, call: &EOFCreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + outcome: &mut CreateOutcome, + ) { // We are processing inner context outputs in the outer context, so need to avoid processing // twice. if self.in_inner_context && ecx.journaled_state.depth == 1 { - return outcome; + return; } - let outcome = self.do_eofcreate_end(ecx, call, outcome); + self.do_eofcreate_end(ecx, call, outcome); if ecx.journaled_state.depth == 0 { self.top_level_frame_end(ecx, outcome.result.result); } - - outcome } fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { call_inspectors!([&mut self.tracer, &mut self.printer], |inspector| { - Inspector::<&mut dyn DatabaseExt>::selfdestruct(inspector, contract, target, value) + Inspector::>::selfdestruct( + inspector, contract, target, value, + ) }); } } @@ -1064,8 +1076,8 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStackRefMut<'_> { impl InspectorExt for InspectorStackRefMut<'_> { fn should_use_create2_factory( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, - inputs: &mut CreateInputs, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, + inputs: &CreateInputs, ) -> bool { call_inspectors!( #[ret] @@ -1091,9 +1103,13 @@ impl InspectorExt for InspectorStackRefMut<'_> { } } -impl Inspector<&mut dyn DatabaseExt> for InspectorStack { +impl Inspector> for InspectorStack { #[inline] - fn step(&mut self, interpreter: &mut Interpreter, ecx: &mut EvmContext<&mut dyn DatabaseExt>) { + fn step( + &mut self, + interpreter: &mut Interpreter, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, + ) { self.as_mut().step(interpreter, ecx) } @@ -1101,14 +1117,14 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStack { fn step_end( &mut self, interpreter: &mut Interpreter, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, ) { self.as_mut().step_end(interpreter, ecx) } fn call( &mut self, - context: &mut EvmContext<&mut dyn DatabaseExt>, + context: &mut EthEvmContext<&mut dyn DatabaseExt>, inputs: &mut CallInputs, ) -> Option { self.as_mut().call(context, inputs) @@ -1116,16 +1132,16 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStack { fn call_end( &mut self, - context: &mut EvmContext<&mut dyn DatabaseExt>, + context: &mut EthEvmContext<&mut dyn DatabaseExt>, inputs: &CallInputs, - outcome: CallOutcome, - ) -> CallOutcome { + outcome: &mut CallOutcome, + ) { self.as_mut().call_end(context, inputs, outcome) } fn create( &mut self, - context: &mut EvmContext<&mut dyn DatabaseExt>, + context: &mut EthEvmContext<&mut dyn DatabaseExt>, create: &mut CreateInputs, ) -> Option { self.as_mut().create(context, create) @@ -1133,16 +1149,16 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStack { fn create_end( &mut self, - context: &mut EvmContext<&mut dyn DatabaseExt>, + context: &mut EthEvmContext<&mut dyn DatabaseExt>, call: &CreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + outcome: &mut CreateOutcome, + ) { self.as_mut().create_end(context, call, outcome) } fn eofcreate( &mut self, - context: &mut EvmContext<&mut dyn DatabaseExt>, + context: &mut EthEvmContext<&mut dyn DatabaseExt>, create: &mut EOFCreateInputs, ) -> Option { self.as_mut().eofcreate(context, create) @@ -1150,17 +1166,17 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStack { fn eofcreate_end( &mut self, - context: &mut EvmContext<&mut dyn DatabaseExt>, + context: &mut EthEvmContext<&mut dyn DatabaseExt>, call: &EOFCreateInputs, - outcome: CreateOutcome, - ) -> CreateOutcome { + outcome: &mut CreateOutcome, + ) { self.as_mut().eofcreate_end(context, call, outcome) } fn initialize_interp( &mut self, interpreter: &mut Interpreter, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, ) { self.as_mut().initialize_interp(interpreter, ecx) } @@ -1168,22 +1184,22 @@ impl Inspector<&mut dyn DatabaseExt> for InspectorStack { fn log( &mut self, interpreter: &mut Interpreter, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, - log: &Log, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, + log: Log, ) { self.as_mut().log(interpreter, ecx, log) } fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { - Inspector::<&mut dyn DatabaseExt>::selfdestruct(&mut self.as_mut(), contract, target, value) + self.as_mut().selfdestruct(contract, target, value); } } impl InspectorExt for InspectorStack { fn should_use_create2_factory( &mut self, - ecx: &mut EvmContext<&mut dyn DatabaseExt>, - inputs: &mut CreateInputs, + ecx: &mut EthEvmContext<&mut dyn DatabaseExt>, + inputs: &CreateInputs, ) -> bool { self.as_mut().should_use_create2_factory(ecx, inputs) } diff --git a/crates/evm/evm/src/lib.rs b/crates/evm/evm/src/lib.rs index 15858c0f393aa..92d39026aa677 100644 --- a/crates/evm/evm/src/lib.rs +++ b/crates/evm/evm/src/lib.rs @@ -11,7 +11,9 @@ extern crate tracing; pub mod executors; pub mod inspectors; -pub use foundry_evm_core::{backend, constants, decode, fork, opts, utils, InspectorExt}; +pub use foundry_evm_core::{ + backend, constants, decode, fork, opts, utils, Env, EnvMut, EvmEnv, InspectorExt, +}; pub use foundry_evm_coverage as coverage; pub use foundry_evm_fuzz as fuzz; pub use foundry_evm_traces as traces; diff --git a/crates/evm/fuzz/src/inspector.rs b/crates/evm/fuzz/src/inspector.rs index 052d87dac2dd1..540e3aa86968f 100644 --- a/crates/evm/fuzz/src/inspector.rs +++ b/crates/evm/fuzz/src/inspector.rs @@ -1,7 +1,9 @@ use crate::{invariant::RandomCallGenerator, strategies::EvmFuzzState}; use revm::{ + context::{ContextTr, Transaction}, + inspector::JournalExt, interpreter::{CallInputs, CallOutcome, CallScheme, Interpreter}, - Database, EvmContext, Inspector, + Inspector, }; /// An inspector that can fuzz and collect data for that effect. @@ -15,9 +17,12 @@ pub struct Fuzzer { pub fuzz_state: EvmFuzzState, } -impl Inspector for Fuzzer { +impl Inspector for Fuzzer +where + CTX: ContextTr, +{ #[inline] - fn step(&mut self, interp: &mut Interpreter, _context: &mut EvmContext) { + fn step(&mut self, interp: &mut Interpreter, _context: &mut CTX) { // We only collect `stack` and `memory` data before and after calls. if self.collect { self.collect_data(interp); @@ -26,9 +31,9 @@ impl Inspector for Fuzzer { } #[inline] - fn call(&mut self, ecx: &mut EvmContext, inputs: &mut CallInputs) -> Option { + fn call(&mut self, ecx: &mut CTX, inputs: &mut CallInputs) -> Option { // We don't want to override the very first call made to the test contract. - if self.call_generator.is_some() && ecx.env.tx.caller != inputs.caller { + if self.call_generator.is_some() && ecx.tx().caller() != inputs.caller { self.override_call(inputs); } @@ -40,12 +45,7 @@ impl Inspector for Fuzzer { } #[inline] - fn call_end( - &mut self, - _context: &mut EvmContext, - _inputs: &CallInputs, - outcome: CallOutcome, - ) -> CallOutcome { + fn call_end(&mut self, _context: &mut CTX, _inputs: &CallInputs, _outcome: &mut CallOutcome) { if let Some(ref mut call_generator) = self.call_generator { call_generator.used = false; } @@ -53,15 +53,13 @@ impl Inspector for Fuzzer { // We only collect `stack` and `memory` data before and after calls. // this will be turned off on the next `step` self.collect = true; - - outcome } } impl Fuzzer { /// Collects `stack` and `memory` values into the fuzz dictionary. fn collect_data(&mut self, interpreter: &Interpreter) { - self.fuzz_state.collect_values(interpreter.stack().data().iter().copied().map(Into::into)); + self.fuzz_state.collect_values(interpreter.stack.data().iter().copied().map(Into::into)); // TODO: disabled for now since it's flooding the dictionary // for index in 0..interpreter.shared_memory.len() / 32 { diff --git a/crates/evm/fuzz/src/strategies/param.rs b/crates/evm/fuzz/src/strategies/param.rs index 43dcdae7b00f3..a8834bcef9942 100644 --- a/crates/evm/fuzz/src/strategies/param.rs +++ b/crates/evm/fuzz/src/strategies/param.rs @@ -235,7 +235,7 @@ mod tests { }; use foundry_common::abi::get_func; use foundry_config::FuzzDictionaryConfig; - use revm::db::{CacheDB, EmptyDB}; + use revm::database::{CacheDB, EmptyDB}; #[test] fn can_fuzz_array() { diff --git a/crates/evm/fuzz/src/strategies/state.rs b/crates/evm/fuzz/src/strategies/state.rs index c598ada0accab..26b66807a7666 100644 --- a/crates/evm/fuzz/src/strategies/state.rs +++ b/crates/evm/fuzz/src/strategies/state.rs @@ -10,9 +10,9 @@ use foundry_config::FuzzDictionaryConfig; use foundry_evm_core::utils::StateChangeset; use parking_lot::{lock_api::RwLockReadGuard, RawRwLock, RwLock}; use revm::{ - db::{CacheDB, DatabaseRef, DbAccount}, - interpreter::opcode, - primitives::AccountInfo, + bytecode::opcode, + database::{CacheDB, DatabaseRef, DbAccount}, + state::AccountInfo, }; use std::{collections::BTreeMap, fmt, sync::Arc}; @@ -39,7 +39,7 @@ impl EvmFuzzState { deployed_libs: &[Address], ) -> Self { // Sort accounts to ensure deterministic dictionary generation from the same setUp state. - let mut accs = db.accounts.iter().collect::>(); + let mut accs = db.cache.accounts.iter().collect::>(); accs.sort_by_key(|(address, _)| *address); // Create fuzz dictionary and insert values from db state. diff --git a/crates/evm/traces/src/debug/mod.rs b/crates/evm/traces/src/debug/mod.rs index 0e6521a7f5a8c..0e07124597aa3 100644 --- a/crates/evm/traces/src/debug/mod.rs +++ b/crates/evm/traces/src/debug/mod.rs @@ -7,7 +7,7 @@ use alloy_dyn_abi::{ use alloy_primitives::U256; use foundry_common::fmt::format_token; use foundry_compilers::artifacts::sourcemap::{Jump, SourceElement}; -use revm::interpreter::OpCode; +use revm::bytecode::opcode::OpCode; use revm_inspectors::tracing::types::{CallTraceStep, DecodedInternalCall, DecodedTraceStep}; pub use sources::{ArtifactData, ContractSources, SourceData}; diff --git a/crates/evm/traces/src/debug/sources.rs b/crates/evm/traces/src/debug/sources.rs index 5c8d15ef19e65..cfd7056e5a8b6 100644 --- a/crates/evm/traces/src/debug/sources.rs +++ b/crates/evm/traces/src/debug/sources.rs @@ -8,7 +8,7 @@ use foundry_compilers::{ multi::MultiCompilerLanguage, Artifact, Compiler, ProjectCompileOutput, }; -use foundry_evm_core::utils::PcIcMap; +use foundry_evm_core::ic::PcIcMap; use foundry_linking::Linker; use rayon::prelude::*; use solar_parse::{interface::Session, Parser}; diff --git a/crates/evm/traces/src/lib.rs b/crates/evm/traces/src/lib.rs index 2107644793463..ab024a2c1f530 100644 --- a/crates/evm/traces/src/lib.rs +++ b/crates/evm/traces/src/lib.rs @@ -15,7 +15,7 @@ use foundry_common::{ contracts::{ContractsByAddress, ContractsByArtifact}, shell, }; -use revm::interpreter::OpCode; +use revm::bytecode::opcode::OpCode; use revm_inspectors::tracing::{ types::{DecodedTraceStep, TraceMemberOrder}, OpcodeFilter, diff --git a/crates/forge/Cargo.toml b/crates/forge/Cargo.toml index c03a708a1f38f..54f2845479cd1 100644 --- a/crates/forge/Cargo.toml +++ b/crates/forge/Cargo.toml @@ -24,6 +24,7 @@ foundry-common.workspace = true foundry-compilers = { workspace = true, features = ["full"] } foundry-config.workspace = true foundry-evm.workspace = true +foundry-evm-core.workspace = true foundry-wallets.workspace = true foundry-linking.workspace = true forge-script-sequence.workspace = true @@ -57,6 +58,8 @@ alloy-serde.workspace = true alloy-signer.workspace = true alloy-transport.workspace = true +revm.workspace = true + clap = { version = "4", features = ["derive", "env", "unicode", "wrap_help"] } clap_complete = "4" clap_complete_fig = "4" diff --git a/crates/forge/src/cmd/coverage.rs b/crates/forge/src/cmd/coverage.rs index 2b656c0be493f..3b2e04eb88b26 100644 --- a/crates/forge/src/cmd/coverage.rs +++ b/crates/forge/src/cmd/coverage.rs @@ -6,7 +6,6 @@ use crate::{ BytecodeReporter, ContractId, CoverageReport, CoverageReporter, CoverageSummaryReporter, DebugReporter, ItemAnchor, LcovReporter, }, - utils::IcPcMap, MultiContractRunnerBuilder, }; use alloy_primitives::{map::HashMap, Address, Bytes, U256}; @@ -23,6 +22,7 @@ use foundry_compilers::{ }; use foundry_config::Config; use foundry_evm::opts::EvmOpts; +use foundry_evm_core::ic::IcPcMap; use rayon::prelude::*; use semver::{Version, VersionReq}; use std::{ diff --git a/crates/forge/src/multi_runner.rs b/crates/forge/src/multi_runner.rs index 03e889c8c5544..9cc608113b711 100644 --- a/crates/forge/src/multi_runner.rs +++ b/crates/forge/src/multi_runner.rs @@ -23,10 +23,11 @@ use foundry_evm::{ opts::EvmOpts, revm, traces::{InternalTraceMode, TraceMode}, + Env, }; use foundry_linking::{LinkOutput, Linker}; use rayon::prelude::*; -use revm::primitives::SpecId; +use revm::primitives::hardfork::SpecId; use std::{ borrow::Borrow, collections::BTreeMap, @@ -249,10 +250,11 @@ impl MultiContractRunner { debug!("start executing all tests in contract"); + let executor = self.tcfg.executor(self.known_contracts.clone(), artifact_id, db.clone()); let runner = ContractRunner::new( &identifier, contract, - self.tcfg.executor(self.known_contracts.clone(), artifact_id, db.clone()), + executor, progress, tokio_handle, span, @@ -279,7 +281,7 @@ pub struct TestRunnerConfig { /// EVM configuration. pub evm_opts: EvmOpts, /// EVM environment. - pub env: revm::primitives::Env, + pub env: Env, /// EVM version. pub spec_id: SpecId, /// The address which will be used to deploy the initial contracts and send all transactions. @@ -472,7 +474,7 @@ impl MultiContractRunnerBuilder { self, root: &Path, output: &ProjectCompileOutput, - env: revm::primitives::Env, + env: Env, evm_opts: EvmOpts, ) -> Result { let contracts = output diff --git a/crates/forge/tests/cli/test_cmd.rs b/crates/forge/tests/cli/test_cmd.rs index 4035cf2a8ae11..1c634c96cb06f 100644 --- a/crates/forge/tests/cli/test_cmd.rs +++ b/crates/forge/tests/cli/test_cmd.rs @@ -2944,7 +2944,7 @@ contract ContractTest { ... Failing tests: Encountered 1 failing test in test/Foo.t.sol:ContractTest -[FAIL: EVM error; transaction validation error: call gas cost exceeds the gas limit] setUp() ([GAS]) +[FAIL: EVM error; transaction validation error: call [GAS_COST] exceeds the [GAS_LIMIT]] setUp() ([GAS]) Encountered a total of 1 failing tests, 0 tests succeeded diff --git a/crates/forge/tests/it/config.rs b/crates/forge/tests/it/config.rs index 022303d51380f..b0f9d8da20a80 100644 --- a/crates/forge/tests/it/config.rs +++ b/crates/forge/tests/it/config.rs @@ -6,12 +6,12 @@ use forge::{ }; use foundry_evm::{ decode::decode_console_logs, - revm::primitives::SpecId, traces::{decode_trace_arena, render_trace_arena, CallTraceDecoderBuilder}, }; use foundry_test_utils::{init_tracing, Filter}; use futures::future::join_all; use itertools::Itertools; +use revm::primitives::hardfork::SpecId; use std::collections::BTreeMap; /// How to execute a test run. diff --git a/crates/forge/tests/it/spec.rs b/crates/forge/tests/it/spec.rs index 52e581c33c921..99a3a5e7a98b2 100644 --- a/crates/forge/tests/it/spec.rs +++ b/crates/forge/tests/it/spec.rs @@ -1,8 +1,8 @@ //! Integration tests for EVM specifications. use crate::{config::*, test_helpers::TEST_DATA_PARIS}; -use foundry_evm::revm::primitives::SpecId; use foundry_test_utils::Filter; +use revm::primitives::hardfork::SpecId; #[tokio::test(flavor = "multi_thread")] async fn test_shanghai_compat() { diff --git a/crates/forge/tests/it/test_helpers.rs b/crates/forge/tests/it/test_helpers.rs index c6ac80c114608..918eabf765a41 100644 --- a/crates/forge/tests/it/test_helpers.rs +++ b/crates/forge/tests/it/test_helpers.rs @@ -2,7 +2,7 @@ use alloy_chains::NamedChain; use alloy_primitives::U256; -use forge::{revm::primitives::SpecId, MultiContractRunner, MultiContractRunnerBuilder}; +use forge::{MultiContractRunner, MultiContractRunnerBuilder}; use foundry_cli::utils::install_crypto_provider; use foundry_compilers::{ artifacts::{EvmVersion, Libraries, Settings}, @@ -19,6 +19,7 @@ use foundry_test_utils::{ fd_lock, init_tracing, rpc::{next_http_archive_rpc_url, next_rpc_endpoint}, }; +use revm::primitives::hardfork::SpecId; use std::{ env, fmt, io::Write, diff --git a/crates/script/src/simulate.rs b/crates/script/src/simulate.rs index 7cd23ee74bace..372cb4b250381 100644 --- a/crates/script/src/simulate.rs +++ b/crates/script/src/simulate.rs @@ -11,7 +11,7 @@ use crate::{ }; use alloy_chains::NamedChain; use alloy_network::TransactionBuilder; -use alloy_primitives::{map::HashMap, utils::format_units, Address, Bytes, TxKind, U256}; +use alloy_primitives::{map::HashMap, utils::format_units, Address, Bytes, TxKind}; use dialoguer::Confirm; use eyre::{Context, Result}; use forge_script_sequence::{ScriptSequence, TransactionWithMetadata}; @@ -139,7 +139,7 @@ impl PreSimulationState { // Simulate mining the transaction if the user passes `--slow`. if self.args.slow { - runner.executor.env_mut().block.number += U256::from(1); + runner.executor.env_mut().evm_env.block_env.number += 1; } let is_noop_tx = if let Some(to) = to { diff --git a/crates/test-utils/src/util.rs b/crates/test-utils/src/util.rs index 42d7e4f6a855e..3179503f28f90 100644 --- a/crates/test-utils/src/util.rs +++ b/crates/test-utils/src/util.rs @@ -1008,6 +1008,8 @@ fn test_redactions() -> snapbox::Redactions { ("[SOLC_VERSION]", r"Solc( version)? \d+.\d+.\d+"), ("[ELAPSED]", r"(finished )?in \d+(\.\d+)?\w?s( \(.*?s CPU time\))?"), ("[GAS]", r"[Gg]as( used)?: \d+"), + ("[GAS_COST]", r"[Gg]as cost\s*\(\d+\)"), + ("[GAS_LIMIT]", r"[Gg]as limit\s*\(\d+\)"), ("[AVG_GAS]", r"μ: \d+, ~: \d+"), ("[FILE]", r"-->.*\.sol"), ("[FILE]", r"Location(.|\n)*\.rs(.|\n)*Backtrace"), diff --git a/crates/verify/Cargo.toml b/crates/verify/Cargo.toml index 8e2ec24f7d4d4..1d3afe7923ced 100644 --- a/crates/verify/Cargo.toml +++ b/crates/verify/Cargo.toml @@ -18,18 +18,19 @@ foundry-config.workspace = true foundry-cli.workspace = true foundry-common.workspace = true foundry-evm.workspace = true +foundry-evm-core.workspace = true serde_json.workspace = true alloy-json-abi.workspace = true alloy-primitives.workspace = true alloy-rpc-types.workspace = true alloy-dyn-abi.workspace = true -revm-primitives.workspace = true serde.workspace = true eyre.workspace = true alloy-provider.workspace = true tracing.workspace = true foundry-compilers = { workspace = true, features = ["full"] } foundry-block-explorers = { workspace = true, features = ["foundry-compilers"] } +revm.workspace = true clap = { version = "4", features = ["derive", "env", "unicode", "wrap_help"] } reqwest = { workspace = true, features = ["json"] } diff --git a/crates/verify/src/bytecode.rs b/crates/verify/src/bytecode.rs index 5c84dbc64d6a0..ee2e96188dab3 100644 --- a/crates/verify/src/bytecode.rs +++ b/crates/verify/src/bytecode.rs @@ -7,7 +7,7 @@ use crate::{ }, verify::VerifierArgs, }; -use alloy_primitives::{hex, Address, Bytes, U256}; +use alloy_primitives::{hex, Address, Bytes, TxKind, U256}; use alloy_provider::{ network::{AnyTxEnvelope, TransactionBuilder}, Provider, @@ -23,7 +23,8 @@ use foundry_common::shell; use foundry_compilers::{artifacts::EvmVersion, info::ContractInfo}; use foundry_config::{figment, impl_figment_convert, Config}; use foundry_evm::{constants::DEFAULT_CREATE2_DEPLOYER, utils::configure_tx_req_env}; -use revm_primitives::{AccountInfo, TxKind}; +use foundry_evm_core::AsEnvMut; +use revm::state::AccountInfo; use std::path::PathBuf; impl_figment_convert!(VerifyBytecodeArgs); @@ -242,7 +243,7 @@ impl VerifyBytecodeArgs { ) .await?; - env.block.number = U256::ZERO; // Genesis block + env.evm_env.block_env.number = 0; let genesis_block = provider.get_block(gen_blk_num.into()).full().await?; // Setup genesis tx and env. @@ -253,15 +254,13 @@ impl VerifyBytecodeArgs { .into_create(); if let Some(ref block) = genesis_block { - configure_env_block(&mut env, block); + configure_env_block(&mut env.as_env_mut(), block); gen_tx_req.max_fee_per_gas = block.header.base_fee_per_gas.map(|g| g as u128); gen_tx_req.gas = Some(block.header.gas_limit); gen_tx_req.gas_price = block.header.base_fee_per_gas.map(|g| g as u128); } - // configure_tx_rq_env(&mut env, &gen_tx); - - configure_tx_req_env(&mut env, &gen_tx_req, None) + configure_tx_req_env(&mut env.as_env_mut(), &gen_tx_req, None) .wrap_err("Failed to configure tx request env")?; // Seed deployer account with funds @@ -444,7 +443,7 @@ impl VerifyBytecodeArgs { evm_opts, ) .await?; - env.block.number = U256::from(simulation_block); + env.evm_env.block_env.number = simulation_block; let block = provider.get_block(simulation_block.into()).full().await?; // Workaround for the NonceTooHigh issue as we're not simulating prior txs of the same @@ -460,7 +459,7 @@ impl VerifyBytecodeArgs { transaction.set_nonce(prev_block_nonce); if let Some(ref block) = block { - configure_env_block(&mut env, block) + configure_env_block(&mut env.as_env_mut(), block) } // Replace the `input` with local creation code in the creation tx. @@ -478,7 +477,7 @@ impl VerifyBytecodeArgs { } // configure_req__env(&mut env, &transaction.inner); - configure_tx_req_env(&mut env, &transaction, None) + configure_tx_req_env(&mut env.as_env_mut(), &transaction, None) .wrap_err("Failed to configure tx request env")?; let fork_address = crate::utils::deploy_contract( diff --git a/crates/verify/src/utils.rs b/crates/verify/src/utils.rs index 81defa05d0f7b..03eef1ff789ae 100644 --- a/crates/verify/src/utils.rs +++ b/crates/verify/src/utils.rs @@ -1,6 +1,6 @@ use crate::{bytecode::VerifyBytecodeArgs, types::VerificationType}; use alloy_dyn_abi::DynSolValue; -use alloy_primitives::{Address, Bytes, U256}; +use alloy_primitives::{Address, Bytes, TxKind}; use alloy_provider::{network::AnyRpcBlock, Provider}; use alloy_rpc_types::BlockId; use clap::ValueEnum; @@ -17,14 +17,10 @@ use foundry_compilers::artifacts::{BytecodeHash, CompactContractBytecode, EvmVer use foundry_config::Config; use foundry_evm::{ constants::DEFAULT_CREATE2_DEPLOYER, executors::TracingExecutor, opts::EvmOpts, - traces::TraceMode, + traces::TraceMode, Env, EnvMut, }; use reqwest::Url; -use revm_primitives::{ - db::Database, - env::{EnvWithHandlerCfg, HandlerCfg}, - Bytecode, Env, SpecId, TxKind, -}; +use revm::{bytecode::Bytecode, database::Database, primitives::hardfork::SpecId}; use semver::Version; use serde::{Deserialize, Serialize}; use yansi::Paint; @@ -330,13 +326,13 @@ pub async fn get_tracing_executor( Ok((env, executor)) } -pub fn configure_env_block(env: &mut Env, block: &AnyRpcBlock) { - env.block.timestamp = U256::from(block.header.timestamp); - env.block.coinbase = block.header.beneficiary; +pub fn configure_env_block(env: &mut EnvMut<'_>, block: &AnyRpcBlock) { + env.block.timestamp = block.header.timestamp; + env.block.beneficiary = block.header.beneficiary; env.block.difficulty = block.header.difficulty; env.block.prevrandao = Some(block.header.mix_hash.unwrap_or_default()); - env.block.basefee = U256::from(block.header.base_fee_per_gas.unwrap_or_default()); - env.block.gas_limit = U256::from(block.header.gas_limit); + env.block.basefee = block.header.base_fee_per_gas.unwrap_or_default(); + env.block.gas_limit = block.header.gas_limit; } pub fn deploy_contract( @@ -345,14 +341,19 @@ pub fn deploy_contract( spec_id: SpecId, to: Option, ) -> Result { - let env_with_handler = EnvWithHandlerCfg::new(Box::new(env.clone()), HandlerCfg::new(spec_id)); + let env = Env::new_with_spec_id( + env.evm_env.cfg_env.clone(), + env.evm_env.block_env.clone(), + env.tx.clone(), + spec_id, + ); if to.is_some_and(|to| to.is_call()) { let TxKind::Call(to) = to.unwrap() else { unreachable!() }; if to != DEFAULT_CREATE2_DEPLOYER { eyre::bail!("Transaction `to` address is not the default create2 deployer i.e the tx is not a contract creation tx."); } - let result = executor.transact_with_env(env_with_handler)?; + let result = executor.transact_with_env(env)?; trace!(transact_result = ?result.exit_reason); if result.result.len() != 20 { @@ -363,7 +364,7 @@ pub fn deploy_contract( Ok(Address::from_slice(&result.result)) } else { - let deploy_result = executor.deploy_with_env(env_with_handler, None)?; + let deploy_result = executor.deploy_with_env(env, None)?; trace!(deploy_result = ?deploy_result.raw.exit_reason); Ok(deploy_result.address) } diff --git a/crates/verify/src/verify.rs b/crates/verify/src/verify.rs index 8fd9c98236a5d..804813c7a96e7 100644 --- a/crates/verify/src/verify.rs +++ b/crates/verify/src/verify.rs @@ -6,7 +6,7 @@ use crate::{ utils::is_host_only, RetryArgs, }; -use alloy_primitives::Address; +use alloy_primitives::{map::HashSet, Address}; use alloy_provider::Provider; use clap::{Parser, ValueHint}; use eyre::Result; @@ -20,7 +20,6 @@ use foundry_compilers::{artifacts::EvmVersion, compilers::solc::Solc, info::Cont use foundry_config::{figment, impl_figment_convert, impl_figment_convert_cast, Config, SolcReq}; use itertools::Itertools; use reqwest::Url; -use revm_primitives::HashSet; use semver::BuildMetadata; use std::path::PathBuf; diff --git a/deny.toml b/deny.toml index 16d88e50ba78f..be6615d08685f 100644 --- a/deny.toml +++ b/deny.toml @@ -40,22 +40,23 @@ confidence-threshold = 0.8 # See https://spdx.org/licenses/ for list of possible licenses # [possible values: any SPDX 3.7 short identifier (+ optional exception)]. allow = [ - "MIT", - "Apache-2.0", + "0BSD", "Apache-2.0 WITH LLVM-exception", + "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", + "BSL-1.0", + "CC0-1.0", + "CDDL-1.0", + "CDLA-Permissive-2.0", "ISC", + "MIT", + "MPL-2.0", + "OpenSSL", "Unicode-3.0", "Unlicense", "WTFPL", - "BSL-1.0", - "0BSD", - "MPL-2.0", - "CDDL-1.0", "Zlib", - "OpenSSL", - "CDLA-Permissive-2.0", ] # Allow 1 or more licenses on a per-crate basis, so that particular licenses @@ -97,6 +98,7 @@ unknown-registry = "warn" unknown-git = "deny" allow-git = [ "https://github.com/alloy-rs/alloy", + "https://github.com/foundry-rs/foundry-fork-db", "https://github.com/paradigmxyz/revm-inspectors", "https://github.com/bluealloy/revm", ] diff --git a/testdata/default/cheats/Fee.t.sol b/testdata/default/cheats/Fee.t.sol index d258eaf13704e..120627c0004e9 100644 --- a/testdata/default/cheats/Fee.t.sol +++ b/testdata/default/cheats/Fee.t.sol @@ -12,7 +12,7 @@ contract FeeTest is DSTest { assertEq(block.basefee, 10, "fee failed"); } - function testFeeFuzzed(uint256 fee) public { + function testFeeFuzzed(uint64 fee) public { vm.fee(fee); assertEq(block.basefee, fee, "fee failed"); } diff --git a/testdata/default/cheats/GetBlockTimestamp.t.sol b/testdata/default/cheats/GetBlockTimestamp.t.sol index edeaa0de79841..816bc0d1ef89e 100644 --- a/testdata/default/cheats/GetBlockTimestamp.t.sol +++ b/testdata/default/cheats/GetBlockTimestamp.t.sol @@ -18,7 +18,7 @@ contract GetBlockTimestampTest is DSTest { assertEq(vm.getBlockTimestamp(), 10, "warp failed"); } - function testGetTimestampWithWarpFuzzed(uint128 jump) public { + function testGetTimestampWithWarpFuzzed(uint32 jump) public { uint256 pre = vm.getBlockTimestamp(); vm.warp(pre + jump); assertEq(vm.getBlockTimestamp(), pre + jump, "warp failed"); diff --git a/testdata/default/cheats/Roll.t.sol b/testdata/default/cheats/Roll.t.sol index 87f909cdd373f..0f26e3a431d7a 100644 --- a/testdata/default/cheats/Roll.t.sol +++ b/testdata/default/cheats/Roll.t.sol @@ -12,7 +12,7 @@ contract RollTest is DSTest { assertEq(block.number, 10, "roll failed"); } - function testRollFuzzed(uint128 jump) public { + function testRollFuzzed(uint32 jump) public { uint256 pre = block.number; vm.roll(block.number + jump); assertEq(block.number, pre + jump, "roll failed"); diff --git a/testdata/default/cheats/Warp.t.sol b/testdata/default/cheats/Warp.t.sol index 42f373c6172f7..7ba53f6e5eda4 100644 --- a/testdata/default/cheats/Warp.t.sol +++ b/testdata/default/cheats/Warp.t.sol @@ -12,7 +12,7 @@ contract WarpTest is DSTest { assertEq(block.timestamp, 10, "warp failed"); } - function testWarpFuzzed(uint128 jump) public { + function testWarpFuzzed(uint32 jump) public { uint256 pre = block.timestamp; vm.warp(block.timestamp + jump); assertEq(block.timestamp, pre + jump, "warp failed"); diff --git a/testdata/default/cheats/getBlockNumber.t.sol b/testdata/default/cheats/getBlockNumber.t.sol index ebf240dd811a1..18e2a163f3b86 100644 --- a/testdata/default/cheats/getBlockNumber.t.sol +++ b/testdata/default/cheats/getBlockNumber.t.sol @@ -17,7 +17,7 @@ contract GetBlockNumberTest is DSTest { assertEq(vm.getBlockNumber(), 10, "could not get correct block height after roll"); } - function testGetBlockNumberWithRollFuzzed(uint128 jump) public { + function testGetBlockNumberWithRollFuzzed(uint32 jump) public { uint256 pre = vm.getBlockNumber(); vm.roll(pre + jump); assertEq(vm.getBlockNumber(), pre + jump, "could not get correct block height after roll");