From 72a9f33ffc7cd4a1ec3d3c6fdb28ba2b9b57717f Mon Sep 17 00:00:00 2001
From: nick199910 <2413810931@qq.com>
Date: Wed, 26 Jun 2024 00:20:21 +0800
Subject: [PATCH 1/6] feature: support corpus from cypo
---
Cargo.lock | 1015 ++++++++++++++++-
Cargo.toml | 8 +
src/evm/blaz/mod.rs | 1 +
src/evm/blaz/offchain_corpus.rs | 461 ++++++++
src/evm/config.rs | 1 +
src/evm/contract_utils.rs | 20 +-
src/evm/corpus_initializer.rs | 10 +
src/evm/mod.rs | 11 +-
src/fuzzers/evm_fuzzer.rs | 53 +-
.../evm_manual/foundry1/test/CreateOpcode.sol | 26 +
...reum__traces__18000000_to_18000000.parquet | Bin 0 -> 473087 bytes
...transactions__18000000_to_18000009.parquet | Bin 0 -> 794686 bytes
12 files changed, 1565 insertions(+), 41 deletions(-)
create mode 100644 src/evm/blaz/offchain_corpus.rs
create mode 100644 tests/evm_manual/foundry1/test/CreateOpcode.sol
create mode 100644 tests/init_cryo_corpus/ethereum__traces__18000000_to_18000000.parquet
create mode 100644 tests/init_cryo_corpus/ethereum__transactions__18000000_to_18000009.parquet
diff --git a/Cargo.lock b/Cargo.lock
index eacb55417..582bec898 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -89,6 +89,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if 1.0.0",
+ "const-random",
"getrandom 0.2.12",
"once_cell",
"version_check",
@@ -142,9 +143,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]]
name = "alloy-chains"
-version = "0.1.15"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e96c81b05c893348760f232c4cc6a6a77fd91cfb09885d4eaad25cd03bd7732e"
+checksum = "cd47e5f8545bdf53beb545d3c039b4afa16040bdf69c50100581579b08776afd"
dependencies = [
"num_enum 0.7.2",
"serde",
@@ -697,6 +698,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "argminmax"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52424b59d69d69d5056d508b260553afd91c57e21849579cd1f50ee8b8b88eaa"
+dependencies = [
+ "num-traits",
+]
+
[[package]]
name = "ark-bls12-381"
version = "0.4.0"
@@ -979,6 +989,12 @@ dependencies = [
"rayon",
]
+[[package]]
+name = "array-init-cursor"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7d0a018de4f6aa429b9d33d69edf69072b1c5b1cb8d3e4a5f7ef898fc3eb76"
+
[[package]]
name = "arrayref"
version = "0.3.7"
@@ -997,6 +1013,99 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
+[[package]]
+name = "arrow-array"
+version = "52.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d33238427c60271710695f17742f45b1a5dc5bcfc5c15331c25ddfe7abf70d97"
+dependencies = [
+ "ahash 0.8.11",
+ "arrow-buffer",
+ "arrow-data",
+ "arrow-schema",
+ "chrono",
+ "half 2.4.0",
+ "hashbrown 0.14.3",
+ "num 0.4.1",
+]
+
+[[package]]
+name = "arrow-buffer"
+version = "52.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe9b95e825ae838efaf77e366c00d3fc8cca78134c9db497d6bda425f2e7b7c1"
+dependencies = [
+ "bytes",
+ "half 2.4.0",
+ "num 0.4.1",
+]
+
+[[package]]
+name = "arrow-cast"
+version = "52.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cf8385a9d5b5fcde771661dd07652b79b9139fea66193eda6a88664400ccab"
+dependencies = [
+ "arrow-array",
+ "arrow-buffer",
+ "arrow-data",
+ "arrow-schema",
+ "arrow-select",
+ "atoi",
+ "base64 0.22.0",
+ "chrono",
+ "half 2.4.0",
+ "lexical-core",
+ "num 0.4.1",
+ "ryu",
+]
+
+[[package]]
+name = "arrow-data"
+version = "52.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb29be98f987bcf217b070512bb7afba2f65180858bca462edf4a39d84a23e10"
+dependencies = [
+ "arrow-buffer",
+ "arrow-schema",
+ "half 2.4.0",
+ "num 0.4.1",
+]
+
+[[package]]
+name = "arrow-ipc"
+version = "52.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffc68f6523970aa6f7ce1dc9a33a7d9284cfb9af77d4ad3e617dbe5d79cc6ec8"
+dependencies = [
+ "arrow-array",
+ "arrow-buffer",
+ "arrow-cast",
+ "arrow-data",
+ "arrow-schema",
+ "flatbuffers",
+]
+
+[[package]]
+name = "arrow-schema"
+version = "52.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32aae6a60458a2389c0da89c9de0b7932427776127da1a738e2efc21d32f3393"
+
+[[package]]
+name = "arrow-select"
+version = "52.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de36abaef8767b4220d7b4a8c2fe5ffc78b47db81b03d77e2136091c3ba39102"
+dependencies = [
+ "ahash 0.8.11",
+ "arrow-array",
+ "arrow-buffer",
+ "arrow-data",
+ "arrow-schema",
+ "num 0.4.1",
+]
+
[[package]]
name = "as-slice"
version = "0.1.5"
@@ -1091,7 +1200,7 @@ version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
dependencies = [
- "brotli",
+ "brotli 3.5.0",
"flate2",
"futures-core",
"memchr",
@@ -1213,6 +1322,21 @@ version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ce4f10ea3abcd6617873bae9f91d1c5332b4a778bd9ce34d0cd517474c1de82"
+[[package]]
+name = "atoi"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
+dependencies = [
+ "num-traits",
+]
+
+[[package]]
+name = "atoi_simd"
+version = "0.15.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ae037714f313c1353189ead58ef9eec30a8e8dc101b2622d461418fd59e28a9"
+
[[package]]
name = "atomic"
version = "0.6.0"
@@ -2148,7 +2272,18 @@ checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
- "brotli-decompressor",
+ "brotli-decompressor 2.5.1",
+]
+
+[[package]]
+name = "brotli"
+version = "6.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+ "brotli-decompressor 4.0.1",
]
[[package]]
@@ -2161,6 +2296,16 @@ dependencies = [
"alloc-stdlib",
]
+[[package]]
+name = "brotli-decompressor"
+version = "4.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362"
+dependencies = [
+ "alloc-no-stdlib",
+ "alloc-stdlib",
+]
+
[[package]]
name = "bs58"
version = "0.4.0"
@@ -2265,6 +2410,20 @@ name = "bytemuck"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b"
+dependencies = [
+ "proc-macro2 1.0.79",
+ "quote 1.0.35",
+ "syn 2.0.57",
+]
[[package]]
name = "byteorder"
@@ -3009,6 +3168,26 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+[[package]]
+name = "const-random"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
+dependencies = [
+ "const-random-macro",
+]
+
+[[package]]
+name = "const-random-macro"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
+dependencies = [
+ "getrandom 0.2.12",
+ "once_cell",
+ "tiny-keccak",
+]
+
[[package]]
name = "const-str"
version = "0.5.7"
@@ -3175,6 +3354,15 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
+dependencies = [
+ "crossbeam-utils",
+]
+
[[package]]
name = "crossbeam-utils"
version = "0.8.19"
@@ -4050,9 +4238,9 @@ dependencies = [
[[package]]
name = "either"
-version = "1.10.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
+checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
[[package]]
name = "elliptic-curve"
@@ -4717,6 +4905,12 @@ dependencies = [
"rand 0.7.3",
]
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
[[package]]
name = "fancy-regex"
version = "0.11.0"
@@ -4727,6 +4921,12 @@ dependencies = [
"regex",
]
+[[package]]
+name = "fast-float"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95765f67b4b18863968b4a1bd5bb576f732b29a4a28c7cd84c09fa3e2875f33c"
+
[[package]]
name = "fastcrypto"
version = "0.1.5"
@@ -4954,6 +5154,16 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+[[package]]
+name = "flatbuffers"
+version = "24.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8add37afff2d4ffa83bc748a70b4b1370984f6980768554182424ef71447c35f"
+dependencies = [
+ "bitflags 1.3.2",
+ "rustc_version 0.4.0",
+]
+
[[package]]
name = "flate2"
version = "1.0.28"
@@ -4994,6 +5204,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+[[package]]
+name = "foreign_vec"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee1b05cbd864bcaecbd3455d6d967862d446e4ebfc3c2e5e5b9841e53cba6673"
+
[[package]]
name = "form_urlencoded"
version = "1.2.1"
@@ -5779,6 +5995,7 @@ checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e"
dependencies = [
"cfg-if 1.0.0",
"crunchy",
+ "num-traits",
]
[[package]]
@@ -5831,6 +6048,7 @@ checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash 0.8.11",
"allocator-api2",
+ "rayon",
"serde",
]
@@ -6637,6 +6855,12 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+[[package]]
+name = "itoap"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9028f49264629065d057f340a86acb84867925865f73bbf8d47b4d149a7e88b8"
+
[[package]]
name = "ityfuzz"
version = "0.1.0"
@@ -6653,6 +6877,7 @@ dependencies = [
"either",
"ethers",
"evmole",
+ "eyre",
"foundry-cheatcodes",
"glob",
"handlebars",
@@ -6670,7 +6895,11 @@ dependencies = [
"nix 0.27.1",
"num_cpus",
"once_cell",
+ "parquet",
"permutator",
+ "polars",
+ "polars-core",
+ "polars-utils",
"primitive-types 0.12.2",
"rand 0.8.5",
"regex",
@@ -7022,6 +7251,70 @@ version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67"
+[[package]]
+name = "lexical-core"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46"
+dependencies = [
+ "lexical-parse-float",
+ "lexical-parse-integer",
+ "lexical-util",
+ "lexical-write-float",
+ "lexical-write-integer",
+]
+
+[[package]]
+name = "lexical-parse-float"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f"
+dependencies = [
+ "lexical-parse-integer",
+ "lexical-util",
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-parse-integer"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9"
+dependencies = [
+ "lexical-util",
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-util"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc"
+dependencies = [
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-write-float"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862"
+dependencies = [
+ "lexical-util",
+ "lexical-write-integer",
+ "static_assertions",
+]
+
+[[package]]
+name = "lexical-write-integer"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446"
+dependencies = [
+ "lexical-util",
+ "static_assertions",
+]
+
[[package]]
name = "libafl"
version = "0.11.2"
@@ -7053,7 +7346,7 @@ dependencies = [
"typed-builder",
"uuid 1.8.0",
"wait-timeout",
- "windows",
+ "windows 0.51.1",
]
[[package]]
@@ -7083,7 +7376,7 @@ dependencies = [
"tuple_list",
"uds",
"uuid 1.8.0",
- "windows",
+ "windows 0.51.1",
"xxhash-rust",
]
@@ -7251,16 +7544,35 @@ dependencies = [
"hashbrown 0.14.3",
]
+[[package]]
+name = "lz4"
+version = "1.25.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6eab492fe7f8651add23237ea56dbf11b3c4ff762ab83d40a47f11433421f91"
+dependencies = [
+ "libc",
+ "lz4-sys",
+]
+
[[package]]
name = "lz4-sys"
-version = "1.9.4"
+version = "1.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900"
+checksum = "e9764018d143cc854c9f17f0b907de70f14393b1f502da6375dce70f00514eb3"
dependencies = [
"cc",
"libc",
]
+[[package]]
+name = "lz4_flex"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5"
+dependencies = [
+ "twox-hash",
+]
+
[[package]]
name = "mach"
version = "0.3.2"
@@ -7349,6 +7661,15 @@ dependencies = [
"libc",
]
+[[package]]
+name = "memmap2"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "memmap2"
version = "0.9.4"
@@ -8413,6 +8734,28 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
+[[package]]
+name = "multiversion"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4851161a11d3ad0bf9402d90ffc3967bf231768bfd7aeb61755ad06dbf1a142"
+dependencies = [
+ "multiversion-macros",
+ "target-features",
+]
+
+[[package]]
+name = "multiversion-macros"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79a74ddee9e0c27d2578323c13905793e91622148f138ba29738f9dddb835e90"
+dependencies = [
+ "proc-macro2 1.0.79",
+ "quote 1.0.35",
+ "syn 1.0.109",
+ "target-features",
+]
+
[[package]]
name = "mysten-metrics"
version = "0.7.0"
@@ -8721,6 +9064,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
+[[package]]
+name = "now"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d89e9874397a1f0a52fc1f197a8effd9735223cb2390e9dcc83ac6cd02923d0"
+dependencies = [
+ "chrono",
+]
+
[[package]]
name = "ntapi"
version = "0.3.7"
@@ -9117,6 +9469,15 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+[[package]]
+name = "ordered-float"
+version = "2.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
+dependencies = [
+ "num-traits",
+]
+
[[package]]
name = "os_info"
version = "3.8.2"
@@ -9354,12 +9715,51 @@ dependencies = [
]
[[package]]
-name = "parse-zoneinfo"
-version = "0.3.0"
+name = "parquet"
+version = "52.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
+checksum = "29c3b5322cc1bbf67f11c079c42be41a55949099b78732f7dba9e15edde40eab"
dependencies = [
- "regex",
+ "ahash 0.8.11",
+ "arrow-array",
+ "arrow-buffer",
+ "arrow-cast",
+ "arrow-data",
+ "arrow-ipc",
+ "arrow-schema",
+ "arrow-select",
+ "base64 0.22.0",
+ "brotli 6.0.0",
+ "bytes",
+ "chrono",
+ "flate2",
+ "half 2.4.0",
+ "hashbrown 0.14.3",
+ "lz4_flex",
+ "num 0.4.1",
+ "num-bigint 0.4.4",
+ "paste",
+ "seq-macro",
+ "snap",
+ "thrift",
+ "twox-hash",
+ "zstd 0.13.0",
+ "zstd-sys",
+]
+
+[[package]]
+name = "parquet-format-safe"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1131c54b167dd4e4799ce762e1ab01549ebb94d5bdd13e6ec1b467491c378e1f"
+
+[[package]]
+name = "parse-zoneinfo"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
+dependencies = [
+ "regex",
]
[[package]]
@@ -9705,6 +10105,15 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+[[package]]
+name = "planus"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc1691dd09e82f428ce8d6310bd6d5da2557c82ff17694d2a32cad7242aea89f"
+dependencies = [
+ "array-init-cursor",
+]
+
[[package]]
name = "plotters"
version = "0.3.5"
@@ -9733,6 +10142,380 @@ dependencies = [
"plotters-backend",
]
+[[package]]
+name = "polars"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e148396dca5496566880fa19374f3f789a29db94e3eb458afac1497b4bac5442"
+dependencies = [
+ "getrandom 0.2.12",
+ "polars-arrow",
+ "polars-core",
+ "polars-error",
+ "polars-io",
+ "polars-lazy",
+ "polars-ops",
+ "polars-parquet",
+ "polars-sql",
+ "polars-time",
+ "polars-utils",
+ "version_check",
+]
+
+[[package]]
+name = "polars-arrow"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cb5e11cd0752ae022fa6ca3afa50a14b0301b7ce53c0135828fbb0f4fa8303e"
+dependencies = [
+ "ahash 0.8.11",
+ "atoi",
+ "atoi_simd",
+ "bytemuck",
+ "chrono",
+ "chrono-tz 0.8.6",
+ "dyn-clone",
+ "either",
+ "ethnum",
+ "fast-float",
+ "foreign_vec",
+ "getrandom 0.2.12",
+ "hashbrown 0.14.3",
+ "itoa",
+ "itoap",
+ "lz4",
+ "multiversion",
+ "num-traits",
+ "polars-arrow-format",
+ "polars-error",
+ "polars-utils",
+ "ryu",
+ "simdutf8",
+ "streaming-iterator",
+ "strength_reduce",
+ "version_check",
+ "zstd 0.13.0",
+]
+
+[[package]]
+name = "polars-arrow-format"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b0ef2474af9396b19025b189d96e992311e6a47f90c53cd998b36c4c64b84c"
+dependencies = [
+ "planus",
+ "serde",
+]
+
+[[package]]
+name = "polars-compute"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89fc4578f826234cdecb782952aa9c479dc49373f81694a7b439c70b6f609ba0"
+dependencies = [
+ "bytemuck",
+ "either",
+ "num-traits",
+ "polars-arrow",
+ "polars-error",
+ "polars-utils",
+ "strength_reduce",
+ "version_check",
+]
+
+[[package]]
+name = "polars-core"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e490c6bace1366a558feea33d1846f749a8ca90bd72a6748752bc65bb4710b2a"
+dependencies = [
+ "ahash 0.8.11",
+ "bitflags 2.5.0",
+ "bytemuck",
+ "chrono",
+ "chrono-tz 0.8.6",
+ "comfy-table 7.1.0",
+ "either",
+ "hashbrown 0.14.3",
+ "indexmap 2.2.6",
+ "num-traits",
+ "once_cell",
+ "polars-arrow",
+ "polars-compute",
+ "polars-error",
+ "polars-row",
+ "polars-utils",
+ "rand 0.8.5",
+ "rand_distr",
+ "rayon",
+ "regex",
+ "smartstring",
+ "thiserror",
+ "version_check",
+ "xxhash-rust",
+]
+
+[[package]]
+name = "polars-error"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08888f58e61599b00f5ea0c2ccdc796b54b9859559cc0d4582733509451fa01a"
+dependencies = [
+ "polars-arrow-format",
+ "regex",
+ "simdutf8",
+ "thiserror",
+]
+
+[[package]]
+name = "polars-expr"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4173591920fe56ad55af025f92eb0d08421ca85705c326a640c43856094e3484"
+dependencies = [
+ "ahash 0.8.11",
+ "bitflags 2.5.0",
+ "once_cell",
+ "polars-arrow",
+ "polars-core",
+ "polars-io",
+ "polars-ops",
+ "polars-plan",
+ "polars-time",
+ "polars-utils",
+ "rayon",
+ "smartstring",
+]
+
+[[package]]
+name = "polars-io"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5842896aea46d975b425d63f156f412aed3cfde4c257b64fb1f43ceea288074e"
+dependencies = [
+ "ahash 0.8.11",
+ "atoi_simd",
+ "bytes",
+ "chrono",
+ "fast-float",
+ "home",
+ "itoa",
+ "memchr",
+ "memmap2 0.7.1",
+ "num-traits",
+ "once_cell",
+ "percent-encoding",
+ "polars-arrow",
+ "polars-core",
+ "polars-error",
+ "polars-time",
+ "polars-utils",
+ "rayon",
+ "regex",
+ "ryu",
+ "simdutf8",
+ "smartstring",
+]
+
+[[package]]
+name = "polars-lazy"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e805ea2ebbc6b7749b0afb31b7fc5d32b42b57ba29b984549d43d3a16114c4a5"
+dependencies = [
+ "ahash 0.8.11",
+ "bitflags 2.5.0",
+ "glob",
+ "once_cell",
+ "polars-arrow",
+ "polars-core",
+ "polars-expr",
+ "polars-io",
+ "polars-ops",
+ "polars-pipe",
+ "polars-plan",
+ "polars-time",
+ "polars-utils",
+ "rayon",
+ "smartstring",
+ "version_check",
+]
+
+[[package]]
+name = "polars-ops"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b0aed7e169c81b98457641cf82b251f52239a668916c2e683abd1f38df00d58"
+dependencies = [
+ "ahash 0.8.11",
+ "argminmax",
+ "base64 0.22.0",
+ "bytemuck",
+ "chrono",
+ "chrono-tz 0.8.6",
+ "either",
+ "hashbrown 0.14.3",
+ "hex",
+ "indexmap 2.2.6",
+ "memchr",
+ "num-traits",
+ "polars-arrow",
+ "polars-compute",
+ "polars-core",
+ "polars-error",
+ "polars-utils",
+ "rayon",
+ "regex",
+ "smartstring",
+ "unicode-reverse",
+ "version_check",
+]
+
+[[package]]
+name = "polars-parquet"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c70670a9e51cac66d0e77fd20b5cc957dbcf9f2660d410633862bb72f846d5b8"
+dependencies = [
+ "ahash 0.8.11",
+ "base64 0.22.0",
+ "ethnum",
+ "num-traits",
+ "parquet-format-safe",
+ "polars-arrow",
+ "polars-error",
+ "polars-utils",
+ "seq-macro",
+ "simdutf8",
+ "streaming-decompression",
+]
+
+[[package]]
+name = "polars-pipe"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a40ae1b3c74ee07e2d1f7cbf56c5d6e15969e45d9b6f0903bd2acaf783ba436"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-queue",
+ "enum_dispatch",
+ "hashbrown 0.14.3",
+ "num-traits",
+ "polars-arrow",
+ "polars-compute",
+ "polars-core",
+ "polars-expr",
+ "polars-io",
+ "polars-ops",
+ "polars-plan",
+ "polars-row",
+ "polars-utils",
+ "rayon",
+ "smartstring",
+ "uuid 1.8.0",
+ "version_check",
+]
+
+[[package]]
+name = "polars-plan"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8daa3541ae7e9af311a4389bc2b21f83349c34c723cc67fa524cdefdaa172d90"
+dependencies = [
+ "ahash 0.8.11",
+ "bytemuck",
+ "chrono-tz 0.8.6",
+ "either",
+ "hashbrown 0.14.3",
+ "once_cell",
+ "percent-encoding",
+ "polars-arrow",
+ "polars-core",
+ "polars-io",
+ "polars-ops",
+ "polars-time",
+ "polars-utils",
+ "rayon",
+ "recursive",
+ "regex",
+ "smartstring",
+ "strum_macros 0.26.2",
+ "version_check",
+]
+
+[[package]]
+name = "polars-row"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "deb285f2f3a65b00dd06bef16bb9f712dbb5478f941dab5cf74f9f016d382e40"
+dependencies = [
+ "bytemuck",
+ "polars-arrow",
+ "polars-error",
+ "polars-utils",
+]
+
+[[package]]
+name = "polars-sql"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a724f699d194cb02c25124d3832f7d4d77f387f1a89ee42f6b9e88ec561d4ad9"
+dependencies = [
+ "hex",
+ "once_cell",
+ "polars-arrow",
+ "polars-core",
+ "polars-error",
+ "polars-lazy",
+ "polars-plan",
+ "rand 0.8.5",
+ "serde",
+ "serde_json",
+ "sqlparser",
+]
+
+[[package]]
+name = "polars-time"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87ebec238d8b6200d9f0c3ce411c8441e950bd5a7df7806b8172d06c1d5a4b97"
+dependencies = [
+ "atoi",
+ "bytemuck",
+ "chrono",
+ "chrono-tz 0.8.6",
+ "now",
+ "once_cell",
+ "polars-arrow",
+ "polars-core",
+ "polars-error",
+ "polars-ops",
+ "polars-utils",
+ "regex",
+ "smartstring",
+]
+
+[[package]]
+name = "polars-utils"
+version = "0.40.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34e1a907c63abf71e5f21467e2e4ff748896c28196746f631c6c25512ec6102c"
+dependencies = [
+ "ahash 0.8.11",
+ "bytemuck",
+ "hashbrown 0.14.3",
+ "indexmap 2.2.6",
+ "num-traits",
+ "once_cell",
+ "polars-error",
+ "raw-cpuid 11.0.2",
+ "rayon",
+ "smartstring",
+ "stacker",
+ "sysinfo 0.30.12",
+ "version_check",
+]
+
[[package]]
name = "polyval"
version = "0.6.2"
@@ -10235,6 +11018,15 @@ dependencies = [
"thiserror",
]
+[[package]]
+name = "psm"
+version = "0.1.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "quanta"
version = "0.9.3"
@@ -10245,7 +11037,7 @@ dependencies = [
"libc",
"mach",
"once_cell",
- "raw-cpuid",
+ "raw-cpuid 10.7.0",
"wasi 0.10.2+wasi-snapshot-preview1",
"web-sys",
"winapi",
@@ -10471,6 +11263,16 @@ dependencies = [
"getrandom 0.2.12",
]
+[[package]]
+name = "rand_distr"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
+dependencies = [
+ "num-traits",
+ "rand 0.8.5",
+]
+
[[package]]
name = "rand_hc"
version = "0.2.0"
@@ -10524,6 +11326,15 @@ dependencies = [
"bitflags 1.3.2",
]
+[[package]]
+name = "raw-cpuid"
+version = "11.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd"
+dependencies = [
+ "bitflags 2.5.0",
+]
+
[[package]]
name = "rayon"
version = "1.10.0"
@@ -10621,6 +11432,26 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "recursive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0786a43debb760f491b1bc0269fe5e84155353c67482b9e60d0cfb596054b43e"
+dependencies = [
+ "recursive-proc-macro-impl",
+ "stacker",
+]
+
+[[package]]
+name = "recursive-proc-macro-impl"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b"
+dependencies = [
+ "quote 1.0.35",
+ "syn 2.0.57",
+]
+
[[package]]
name = "redox_syscall"
version = "0.2.16"
@@ -11143,9 +11974,9 @@ dependencies = [
[[package]]
name = "ruint"
-version = "1.12.1"
+version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62"
+checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286"
dependencies = [
"alloy-rlp",
"arbitrary",
@@ -11168,9 +11999,9 @@ dependencies = [
[[package]]
name = "ruint-macro"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343"
+checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18"
[[package]]
name = "rusb"
@@ -11877,6 +12708,12 @@ dependencies = [
"uuid 1.8.0",
]
+[[package]]
+name = "seq-macro"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
+
[[package]]
name = "serde"
version = "1.0.197"
@@ -12295,6 +13132,12 @@ dependencies = [
"rand_core 0.6.4",
]
+[[package]]
+name = "simdutf8"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a"
+
[[package]]
name = "similar"
version = "2.5.0"
@@ -12374,6 +13217,17 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+[[package]]
+name = "smartstring"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
+dependencies = [
+ "autocfg",
+ "static_assertions",
+ "version_check",
+]
+
[[package]]
name = "snap"
version = "1.1.1"
@@ -12471,12 +13325,34 @@ dependencies = [
"der 0.7.8",
]
+[[package]]
+name = "sqlparser"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "743b4dc2cbde11890ccb254a8fc9d537fa41b36da00de2a1c5e9848c9bc42bd7"
+dependencies = [
+ "log",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+[[package]]
+name = "stacker"
+version = "0.1.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce"
+dependencies = [
+ "cc",
+ "cfg-if 1.0.0",
+ "libc",
+ "psm",
+ "winapi",
+]
+
[[package]]
name = "static_assertions"
version = "1.1.0"
@@ -12495,6 +13371,27 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
+[[package]]
+name = "streaming-decompression"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf6cc3b19bfb128a8ad11026086e31d3ce9ad23f8ea37354b31383a187c44cf3"
+dependencies = [
+ "fallible-streaming-iterator",
+]
+
+[[package]]
+name = "streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520"
+
+[[package]]
+name = "strength_reduce"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82"
+
[[package]]
name = "string_cache"
version = "0.8.7"
@@ -12954,6 +13851,20 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "sysinfo"
+version = "0.30.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "732ffa00f53e6b2af46208fba5718d9662a421049204e156328b66791ffa15ae"
+dependencies = [
+ "cfg-if 1.0.0",
+ "core-foundation-sys",
+ "libc",
+ "ntapi 0.4.1",
+ "once_cell",
+ "windows 0.52.0",
+]
+
[[package]]
name = "system-configuration"
version = "0.5.1"
@@ -13015,6 +13926,12 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
+[[package]]
+name = "target-features"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1bbb9f3c5c463a01705937a24fdabc5047929ac764b2d5b9cf681c1f5041ed5"
+
[[package]]
name = "target-lexicon"
version = "0.12.14"
@@ -13214,6 +14131,17 @@ dependencies = [
"num_cpus",
]
+[[package]]
+name = "thrift"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09"
+dependencies = [
+ "byteorder",
+ "integer-encoding",
+ "ordered-float",
+]
+
[[package]]
name = "time"
version = "0.1.43"
@@ -14206,6 +15134,15 @@ dependencies = [
"tinyvec",
]
+[[package]]
+name = "unicode-reverse"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b6f4888ebc23094adfb574fdca9fdc891826287a6397d2cd28802ffd6f20c76"
+dependencies = [
+ "unicode-segmentation",
+]
+
[[package]]
name = "unicode-segmentation"
version = "1.11.0"
@@ -14658,6 +15595,16 @@ dependencies = [
"windows-targets 0.48.5",
]
+[[package]]
+name = "windows"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
+dependencies = [
+ "windows-core 0.52.0",
+ "windows-targets 0.52.4",
+]
+
[[package]]
name = "windows-core"
version = "0.51.1"
@@ -15060,8 +16007,8 @@ dependencies = [
"block-padding 0.2.1",
"block-padding 0.3.3",
"blst",
- "brotli",
- "brotli-decompressor",
+ "brotli 3.5.0",
+ "brotli-decompressor 2.5.1",
"bs58 0.4.0",
"bstr",
"bulletproofs",
@@ -15559,7 +16506,7 @@ dependencies = [
"rand_core 0.6.4",
"rand_xorshift",
"rand_xoshiro",
- "raw-cpuid",
+ "raw-cpuid 10.7.0",
"rayon",
"rayon-core",
"rcgen",
@@ -15692,7 +16639,7 @@ dependencies = [
"syn 2.0.57",
"sync_wrapper",
"synstructure",
- "sysinfo",
+ "sysinfo 0.27.8",
"tabled",
"tabled_derive",
"tabular",
@@ -16033,6 +16980,15 @@ dependencies = [
"zstd-safe 6.0.6",
]
+[[package]]
+name = "zstd"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
+dependencies = [
+ "zstd-safe 7.0.0",
+]
+
[[package]]
name = "zstd-safe"
version = "5.0.2+zstd.1.5.2"
@@ -16053,11 +17009,20 @@ dependencies = [
"zstd-sys",
]
+[[package]]
+name = "zstd-safe"
+version = "7.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
+dependencies = [
+ "zstd-sys",
+]
+
[[package]]
name = "zstd-sys"
-version = "2.0.10+zstd.1.5.6"
+version = "2.0.9+zstd.1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa"
+checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
dependencies = [
"cc",
"pkg-config",
diff --git a/Cargo.toml b/Cargo.toml
index f00806caa..78fbd2d54 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -124,6 +124,7 @@ alloy-sol-types = "0.6"
alloy-dyn-abi = { version = "0.6", features = ["arbitrary", "eip712"] }
alloy-primitives = "0.6"
alloy-json-abi = "0.6"
+
# error handling
anyhow = "1.0"
thiserror = "1.0"
@@ -133,3 +134,10 @@ tracing-subscriber = "0.3"
colored = "2.0"
evmole = "0.3.2"
semver = "1.0.22"
+
+parquet = "52.0.0"
+polars-core = "0.40.0"
+polars-utils = "0.40.0"
+polars = "0.40.0"
+
+eyre = "0.6.12"
\ No newline at end of file
diff --git a/src/evm/blaz/mod.rs b/src/evm/blaz/mod.rs
index 58d9d05c5..e7b7b169b 100644
--- a/src/evm/blaz/mod.rs
+++ b/src/evm/blaz/mod.rs
@@ -14,6 +14,7 @@ pub mod builder;
pub(crate) mod linking;
pub mod offchain_artifacts;
pub mod offchain_config;
+pub mod offchain_corpus;
fn get_client() -> reqwest::blocking::Client {
reqwest::blocking::Client::builder()
diff --git a/src/evm/blaz/offchain_corpus.rs b/src/evm/blaz/offchain_corpus.rs
new file mode 100644
index 000000000..db0603667
--- /dev/null
+++ b/src/evm/blaz/offchain_corpus.rs
@@ -0,0 +1,461 @@
+use std::{
+ cmp::Ordering,
+ collections::{BTreeMap, HashMap},
+ default::Default,
+ fs::File,
+ path::Path,
+ process,
+ str::FromStr,
+ sync::Arc,
+};
+
+use alloy_primitives::{BlockNumber, B256};
+use alloy_sol_types::SolValue;
+use bytes::Bytes;
+use ethers::{
+ abi::{ethereum_types, AbiEncode},
+ prelude::{
+ CallFrame,
+ GethDebugBuiltInTracerConfig,
+ GethDebugBuiltInTracerType,
+ GethDebugBuiltInTracerType::PreStateTracer,
+ GethDebugTracerConfig,
+ GethDebugTracerType,
+ GethDebugTracingOptions,
+ Http,
+ PreStateConfig,
+ PreStateFrame,
+ Provider,
+ ProviderExt,
+ },
+ providers::Middleware,
+ types::{AccountState, Address, Transaction, U256, U64},
+};
+use libafl::prelude::{Scheduler, StdMapObserver};
+use parquet::{
+ file::reader::{FileReader, SerializedFileReader},
+ record::{Field, Row},
+};
+use primitive_types::H256;
+use revm_interpreter::BytecodeLocked;
+use revm_primitives::{BlockEnv, Bytecode, Env};
+
+use crate::{
+ evm::{
+ abi::{get_abi_type_boxed, BoxedABI},
+ contract_utils::to_hex_string,
+ host::FuzzHost,
+ input::{ConciseEVMInput, EVMInput, EVMInputTy::ABI},
+ scheduler::PowerABIScheduler,
+ types::{EVMAddress, EVMFuzzState, EVMStagedVMState},
+ vm::EVMState,
+ EVMU256,
+ },
+ executor::FuzzExecutor,
+};
+
+pub type GethStateUpdate = BTreeMap
;
+#[derive(Clone, Debug, Default)]
+pub struct ActionTransaction {
+ action_from: Option,
+ action_to: Option,
+ action_value: Option,
+ action_gas: Option,
+ action_input: Option,
+ action_call_type: Option,
+ action_init: Option,
+ action_reward_type: Option,
+ action_type: Option,
+ result_gas_used: Option,
+ result_output: Option,
+ result_code: Option,
+ result_address: Option,
+ trace_address: Option,
+ subtraces: Option,
+ transaction_index: Option,
+ transaction_hash: Option,
+ block_number: Option,
+ block_hash: Option,
+ error: Option,
+ chain_id: Option,
+}
+
+pub type CryoTestcases = Vec<(Vec, GethStateUpdate)>;
+
+#[derive(Clone, Debug, Default)]
+pub struct OffchainCorpus;
+
+impl OffchainCorpus {
+ fn parse_row(row: Row) -> ActionTransaction {
+ let mut action = ActionTransaction {
+ action_from: None,
+ action_to: None,
+ action_value: None,
+ action_gas: None,
+ action_input: None,
+ action_call_type: None,
+ action_init: None,
+ action_reward_type: None,
+ action_type: None,
+ result_gas_used: None,
+ result_output: None,
+ result_code: None,
+ result_address: None,
+ trace_address: None,
+ subtraces: None,
+ transaction_index: None,
+ transaction_hash: None,
+ block_number: None,
+ block_hash: None,
+ error: None,
+ chain_id: None,
+ };
+
+ for (name, field) in row.get_column_iter() {
+ match name.as_str() {
+ "action_from" => action.action_from = Self::field_to_string(field),
+ "action_to" => action.action_to = Self::field_to_string(field),
+ "action_value" => action.action_value = Self::field_to_string(field),
+ "action_gas" => action.action_gas = Self::field_to_u32(field),
+ "action_input" => action.action_input = Self::field_to_string(field),
+ "action_call_type" => action.action_call_type = Self::field_to_string(field),
+ "action_init" => action.action_init = Self::field_to_string(field),
+ "action_reward_type" => action.action_reward_type = Self::field_to_string(field),
+ "action_type" => action.action_type = Self::field_to_string(field),
+ "result_gas_used" => action.result_gas_used = Self::field_to_u32(field),
+ "result_output" => action.result_output = Self::field_to_string(field),
+ "result_code" => action.result_code = Self::field_to_string(field),
+ "result_address" => action.result_address = Self::field_to_string(field),
+ "trace_address" => action.trace_address = Self::field_to_string(field),
+ "subtraces" => action.subtraces = Self::field_to_u32(field),
+ "transaction_index" => action.transaction_index = Self::field_to_u32(field),
+ "transaction_hash" => action.transaction_hash = Self::field_to_string(field),
+ "block_number" => action.block_number = Self::field_to_u32(field),
+ "block_hash" => action.block_hash = Self::field_to_string(field),
+ "error" => action.error = Self::field_to_string(field),
+ "chain_id" => action.chain_id = Self::field_to_u64(field),
+ _ => (),
+ }
+ }
+ action
+ }
+
+ async fn action_transaction_to_tx(rpc_url: &str, ac_txs: &Vec) -> CryoTestcases {
+ let mut input = vec![];
+ for ac_tx in ac_txs {
+ let tx_hash = ac_tx.clone().transaction_hash.unwrap();
+ let from = Address::from_str(ac_tx.clone().action_from.unwrap().as_str()).unwrap();
+ let to = Address::from_str(ac_tx.clone().action_to.unwrap().as_str()).unwrap();
+ let value = if ac_tx.clone().action_value.is_some() {
+ EVMU256::from_str(ac_tx.clone().action_value.unwrap().as_str())
+ } else {
+ Ok(EVMU256::default())
+ }
+ .unwrap();
+ let input_data = ac_tx.clone().action_input.unwrap();
+ let abi_data = get_abi_type_boxed(input_data.as_str());
+ let env = Self::get_call_env(rpc_url, tx_hash.clone()).await; // rpc req
+
+ let ret = ConciseEVMInput {
+ input_type: ABI,
+ caller: from.into(),
+ contract: to.into(),
+ #[cfg(not(feature = "debug"))]
+ data: Some(abi_data),
+ txn_value: Some(value.into()),
+ step: false,
+ env,
+ liquidation_percent: 0,
+ randomness: vec![],
+ repeat: 0,
+ layer: 0,
+ call_leak: 0,
+ return_data: None,
+ swap_data: Default::default(),
+ #[cfg(feature = "debug")]
+ direct_data: input_data,
+ };
+
+ // gen account state
+ let pre_state = Self::pre_state_trace_transaction(rpc_url, tx_hash.clone())
+ .await
+ .expect("TODO: panic message");
+ let testcase = vec![ret];
+
+ input.push((testcase, pre_state));
+ }
+ input
+ }
+
+ fn field_to_string(field: &Field) -> Option {
+ match field {
+ Field::Bytes(bytes) => Some(to_hex_string(bytes.data())),
+ Field::Str(s) => Some(s.to_string()),
+ Field::Null => None,
+ _ => None,
+ }
+ }
+
+ fn field_to_u32(field: &Field) -> Option {
+ match field {
+ Field::Int(val) => Some(*val as u32),
+ Field::Null => None,
+ _ => None,
+ }
+ }
+
+ fn field_to_u64(field: &Field) -> Option {
+ match field {
+ Field::Long(val) => Some(*val as u64),
+ Field::Null => None,
+ _ => None,
+ }
+ }
+
+ pub fn dfs_call_trace(call_frames: &[CallFrame], transaction: &mut Vec, env: Env) {
+ for frame in call_frames {
+ let abi = BoxedABI::default();
+ let txn_value = if frame.clone().value.is_some() {
+ Some(U256::from(frame.clone().value.unwrap().encode().as_slice()).into())
+ } else {
+ None
+ };
+ let tx = ConciseEVMInput {
+ input_type: ABI,
+ caller: frame.clone().from.into(),
+ contract: frame.clone().to.unwrap().as_address().unwrap().0.into(),
+ #[cfg(not(feature = "debug"))]
+ data: Some(abi),
+ txn_value,
+ step: false,
+ env: Default::default(),
+ liquidation_percent: 0,
+ randomness: vec![],
+ repeat: 0,
+ layer: 0,
+ call_leak: 0,
+ return_data: None,
+ swap_data: Default::default(),
+ #[cfg(feature = "debug")]
+ direct_data: "".to_string(),
+ };
+ transaction.push(tx.clone());
+ }
+ }
+
+ pub async fn get_call_env(rpc_url: &str, tx_hash: String) -> Env {
+ let provider = Provider::try_connect(rpc_url).await.expect("rpc connect error");
+ let req = H256::from_str(tx_hash.as_str()).unwrap();
+ let tx = provider
+ .get_transaction(req)
+ .await
+ .expect("tx_hash or rpc error")
+ .unwrap();
+ let block_id = tx.block_number.unwrap().as_u64();
+ let block_rep = provider
+ .get_block(block_id)
+ .await
+ .expect("block_number error ")
+ .unwrap();
+ println!("block number is {:?}", tx.block_number.unwrap().as_usize());
+ let block_env = BlockEnv {
+ number: U256::from(tx.block_number.unwrap().as_usize()).into(),
+ coinbase: Default::default(),
+ timestamp: block_rep.clone().timestamp.into(),
+ difficulty: block_rep.clone().difficulty.into(),
+ prevrandao: None,
+ basefee: Default::default(),
+ gas_limit: Default::default(),
+ };
+ Env {
+ cfg: Default::default(),
+ block: block_env,
+ tx: Default::default(),
+ }
+ }
+
+ pub async fn call_trace_transaction(rpc_url: &str, tx_hash: String) -> CallFrame {
+ let provider = Provider::try_connect(rpc_url).await.expect("rpc connect error");
+ let req = H256::from_str(tx_hash.as_str()).unwrap();
+
+ let options = GethDebugTracingOptions {
+ disable_storage: Some(true),
+ enable_memory: Some(false),
+ tracer: Some(GethDebugTracerType::BuiltInTracer(
+ GethDebugBuiltInTracerType::CallTracer,
+ )),
+ ..Default::default()
+ };
+
+ let tracer_info = provider
+ .debug_trace_transaction(req, options)
+ .await
+ .expect("tracer error");
+
+ let call_tracer = match tracer_info {
+ ethers::types::GethTrace::Known(geth_tracer_frame) => match geth_tracer_frame {
+ ethers::types::GethTraceFrame::CallTracer(pre_state_frame) => pre_state_frame,
+ _ => todo!(),
+ },
+ _ => todo!(),
+ };
+ // println!("call_tracer is {:?}", call_tracer);
+ call_tracer
+ }
+
+ pub async fn pre_state_trace_transaction(rpc_url: &str, tx_hash: String) -> eyre::Result {
+ let provider = Provider::try_connect(rpc_url).await.expect("rpc connect error");
+ let req = H256::from_str(tx_hash.as_str()).unwrap();
+
+ let tracer_config =
+ GethDebugTracerConfig::BuiltInTracer(GethDebugBuiltInTracerConfig::PreStateTracer(PreStateConfig {
+ diff_mode: Some(false),
+ }));
+
+ let mut options = GethDebugTracingOptions::default();
+ options.tracer = Some(GethDebugTracerType::BuiltInTracer(PreStateTracer));
+ options.tracer_config = Some(tracer_config);
+
+ let tracer_info = provider
+ .debug_trace_transaction(req, options)
+ .await
+ .unwrap_or_else(|err| {
+ eprintln!("transaction reverted with err: {}", err);
+ process::exit(1);
+ });
+
+ match tracer_info {
+ ethers::types::GethTrace::Known(geth_tracer_frame) => match geth_tracer_frame {
+ ethers::types::GethTraceFrame::PreStateTracer(pre_state_frame) => match pre_state_frame {
+ PreStateFrame::Default(default_mode) => Ok(default_mode.0),
+ PreStateFrame::Diff(_) => Ok(GethStateUpdate::default()),
+ },
+ _ => todo!(),
+ },
+ _ => todo!(),
+ }
+ }
+
+ pub async fn generate_testcases_from_txhash(rpc_url: &str, tx_hashs: Vec) -> CryoTestcases {
+ let mut cryo_testcases = vec![];
+ for tx_hash in tx_hashs {
+ let pre_state = Self::pre_state_trace_transaction(rpc_url, tx_hash.clone())
+ .await
+ .expect("TODO: panic message");
+ let call_tracer = Self::call_trace_transaction(rpc_url, tx_hash.clone()).await;
+ let vec_call_tracer = vec![call_tracer];
+ let mut test_case: Vec = vec![];
+ let env = Self::get_call_env(rpc_url, tx_hash.clone()).await;
+ OffchainCorpus::dfs_call_trace(&vec_call_tracer, &mut test_case, env);
+ cryo_testcases.push((test_case, pre_state));
+ }
+ cryo_testcases
+ }
+
+ pub async fn generate_testcases(rpc_url: &str, cryo_parquet_file_path: &str) -> CryoTestcases {
+ println!("cryo_parquet_file_path: {:?}", cryo_parquet_file_path);
+ let file = File::open(&Path::new(&cryo_parquet_file_path)).expect("Couldn't open parquet data");
+ let reader = SerializedFileReader::new(file).unwrap();
+ let parquet_metadata = reader.metadata();
+
+ // let num_rows = parquet_metadata.file_metadata().num_rows();
+ // println!("Number of rows: {}", num_rows);
+
+ let mut iter = reader.get_row_iter(None).unwrap();
+ let mut action_txs = vec![];
+ while let Some(record) = iter.next() {
+ if record.is_ok() {
+ let action = Self::parse_row(record.unwrap());
+ if action.action_to.is_none() ||
+ action.transaction_hash.is_none() ||
+ action.action_from.is_none() ||
+ action.action_input.is_none()
+ {
+ continue;
+ }
+ action_txs.push(action);
+ }
+ }
+ let txs = if !action_txs.is_empty() {
+ Self::action_transaction_to_tx(rpc_url, &action_txs).await
+ } else {
+ CryoTestcases::default()
+ };
+ txs
+ }
+
+ pub fn generate_testcases_sync(rpc_url: &str, cryo_parquet_file_path: &str) -> CryoTestcases {
+ let rt = tokio::runtime::Runtime::new().unwrap();
+ rt.block_on(Self::generate_testcases(rpc_url, cryo_parquet_file_path))
+ }
+
+ pub fn generate_vm_state_from_pre_state(tx_state: &(Vec, GethStateUpdate)) -> EVMStagedVMState {
+ let mut evm_state = EVMStagedVMState::default();
+ let state = &tx_state.1;
+ let _ = state.into_iter().map(|account_state| {
+ let address = account_state.0 .0;
+ let address = EVMAddress::from_slice(&address);
+
+ if account_state.1.storage.is_some() {
+ let slots = account_state.1.clone().storage.unwrap();
+ let accounts_state = slots
+ .into_iter()
+ .map(|item| {
+ let key = EVMU256::from_be_slice(&item.0 .0);
+ let value = EVMU256::from_be_slice(&item.1 .0);
+ (key, value)
+ })
+ .collect();
+ evm_state.state.state.insert(address, accounts_state);
+ }
+ });
+ evm_state
+ }
+
+ pub fn generate_vm_accounts_from_pre_state(
+ rpc_url: &str,
+ fuzz_host: &mut FuzzHost>,
+ cryo_parquet_file_path: &str,
+ ) {
+ for tx_state in &Self::generate_testcases_sync(rpc_url, cryo_parquet_file_path) {
+ // insert account state to host
+ let state = &tx_state.1;
+ let _ = state.into_iter().map(|account_state| {
+ let bytecode = Arc::new(
+ BytecodeLocked::try_from(Bytecode::new_raw(Bytes::from(account_state.1.clone().code.unwrap())))
+ .unwrap(),
+ );
+ let address = account_state.0 .0;
+ let address = EVMAddress::from_slice(&address);
+ fuzz_host.code.insert(address, bytecode)
+ });
+ }
+ }
+}
+
+mod test {
+ use revm_primitives::Env;
+
+ use crate::evm::{blaz::offchain_corpus::OffchainCorpus, input::ConciseEVMInput};
+
+ #[test]
+ fn test_new_offchain_corpus() {
+ let corpus_path = "/Users/wangchao/work/test_ityfuzz/ityfuzz/tests/init_cryo_corpus/ethereum__traces__18000000_to_18000000.parquet";
+ let rpc_url = "https://lb.nodies.app/v1/181a5ebf4c954f8496ae7cbc1ac8d03b";
+ }
+
+ #[test]
+ fn test_generate_testcases() {
+ let rpc_url = "https://lb.nodies.app/v1/181a5ebf4c954f8496ae7cbc1ac8d03b";
+
+ // let testcase = OffchainCorpus::generate_testcases_sync(rpc_url,
+ // vec_tx_hash); println!("test_case is {:?}", testcase);
+ }
+
+ #[test]
+ fn remove_first() {
+ let mut items = vec![1, 2, 3];
+ items.remove(0);
+ println!("after remove items is {:?}", items);
+ }
+}
diff --git a/src/evm/config.rs b/src/evm/config.rs
index d8b96878d..49c7fb5bf 100644
--- a/src/evm/config.rs
+++ b/src/evm/config.rs
@@ -92,6 +92,7 @@ pub struct Config {
pub load_corpus: String,
#[cfg(feature = "use_presets")]
pub preset_file_path: String,
+ pub load_crypo_corpus: Option,
}
impl Debug
diff --git a/src/evm/contract_utils.rs b/src/evm/contract_utils.rs
index 3a3358ba8..42e01845f 100644
--- a/src/evm/contract_utils.rs
+++ b/src/evm/contract_utils.rs
@@ -1246,18 +1246,14 @@ impl ContractLoader {
}
}
- evm_executor.host.env.block.number = EVMU256::from(
- u64::from_str_radix(
- &onchain_middleware
- .as_ref()
- .unwrap()
- .endpoint
- .block_number
- .trim_start_matches("0x"),
- 16,
- )
- .unwrap(),
- );
+ match &onchain_middleware {
+ Some(onchain) => {
+ evm_executor.host.env.block.number = EVMU256::from(
+ u64::from_str_radix(onchain.endpoint.block_number.trim_start_matches("0x"), 16).unwrap(),
+ );
+ }
+ None => {}
+ }
SetupData {
evmstate: new_vm_state,
diff --git a/src/evm/corpus_initializer.rs b/src/evm/corpus_initializer.rs
index 8e49345cd..e07b971b3 100644
--- a/src/evm/corpus_initializer.rs
+++ b/src/evm/corpus_initializer.rs
@@ -289,6 +289,11 @@ where
}
}
+ pub fn initialize_corpus_with_crypo(&mut self, loader: &mut ContractLoader) -> EVMInitializationArtifacts {
+ todo!()
+ // 1.
+ }
+
pub fn initialize_corpus(&mut self, loader: &mut ContractLoader) -> EVMInitializationArtifacts {
let mut artifacts = EVMInitializationArtifacts {
address_to_bytecode: HashMap::new(),
@@ -581,3 +586,8 @@ where
}
}
}
+
+mod test {
+ #[test]
+ fn test_load_crypo() {}
+}
diff --git a/src/evm/mod.rs b/src/evm/mod.rs
index 4f1896156..f1bf236d1 100644
--- a/src/evm/mod.rs
+++ b/src/evm/mod.rs
@@ -100,7 +100,7 @@ struct RPCCall {
}
/// CLI for ItyFuzz for EVM smart contracts
-#[derive(Parser, Debug, Default)]
+#[derive(Parser, Debug, Default, Clone)]
#[command(author, version, about, long_about = None, trailing_var_arg = true, allow_hyphen_values = true)]
pub struct EvmArgs {
/// Glob pattern / address to find contracts
@@ -269,6 +269,10 @@ pub struct EvmArgs {
#[arg(long, default_value = "")]
load_corpus: String,
+ /// Load corpus from crypo. If not specified, will use empty corpus.
+ #[arg(long, short = 'l', default_value = None)]
+ load_crypo_corpus: Option,
+
/// [DEPRECATED] Specify the setup file that deploys all the contract.
/// Fuzzer invokes setUp() to deploy.
#[arg(long, default_value = "")]
@@ -812,6 +816,7 @@ pub fn evm_main(mut args: EvmArgs) {
preset_file_path: args.preset_file_path,
load_corpus: args.load_corpus,
etherscan_api_key,
+ load_crypo_corpus: args.load_crypo_corpus,
};
let mut abis_map: HashMap>> = HashMap::new();
@@ -837,6 +842,9 @@ pub fn evm_main(mut args: EvmArgs) {
let abis_json = format!("{}/abis.json", args.work_dir.clone().as_str());
utils::try_write_file(&abis_json, &json_str, true).unwrap();
+
+ // load crypo_corpus tx
+
evm_fuzzer(config, &mut state)
}
@@ -987,6 +995,7 @@ fn test_evm_offchain_setup() {
preset_file_path: args.preset_file_path,
load_corpus: args.load_corpus,
etherscan_api_key: String::from(""),
+ load_crypo_corpus: args.load_crypo_corpus,
};
let mut abis_map: HashMap>> = HashMap::new();
diff --git a/src/fuzzers/evm_fuzzer.rs b/src/fuzzers/evm_fuzzer.rs
index bac6f5081..1a5b63a8f 100644
--- a/src/fuzzers/evm_fuzzer.rs
+++ b/src/fuzzers/evm_fuzzer.rs
@@ -16,7 +16,7 @@ use tracing::{debug, error, info};
use crate::{
evm::{
abi::{ABIAddressToInstanceMap, BoxedABI},
- blaz::builder::ArtifactInfoMetadata,
+ blaz::{builder::ArtifactInfoMetadata, offchain_corpus::OffchainCorpus},
concolic::{
concolic_host::CONCOLIC_TIMEOUT,
concolic_stage::{ConcolicFeedbackWrapper, ConcolicStage},
@@ -88,6 +88,7 @@ pub fn evm_fuzzer(
state: &mut EVMFuzzState,
) {
info!("\n\n ================ EVM Fuzzer Start ===================\n\n");
+ // read tx info from crypo_path
// create work dir if not exists
let _path = Path::new(config.work_dir.as_str());
@@ -104,7 +105,8 @@ pub fn evm_fuzzer(
let jmp_observer = unsafe { StdMapObserver::new("jmp", jmps) };
let deployer = fixed_address(FIX_DEPLOYER);
- let mut fuzz_host = FuzzHost::new(scheduler.clone(), config.work_dir.clone());
+ let mut fuzz_host: FuzzHost> =
+ FuzzHost::new(scheduler.clone(), config.work_dir.clone());
fuzz_host.set_spec_id(config.spec_id);
// **Note**: cheatcode should be the first middleware because it consumes the
@@ -194,6 +196,7 @@ pub fn evm_fuzzer(
fuzz_host.add_flashloan_middleware(Flashloan::new(true, chain_cfg, config.flashloan_oracle));
}
}
+
let sha3_taint = Rc::new(RefCell::new(Sha3TaintAnalysis::new()));
if config.sha3_bypass {
@@ -206,6 +209,13 @@ pub fn evm_fuzzer(
fuzz_host.add_middlewares(Rc::new(RefCell::new(ReentrancyTracer::new())));
}
+ // load all bytecode
+ if config.load_crypo_corpus.is_some() {
+ let crypo_corpus = config.load_crypo_corpus.clone().unwrap();
+ let rpc_url = "https://lb.nodies.app/v1/181a5ebf4c954f8496ae7cbc1ac8d03b";
+ OffchainCorpus::generate_vm_accounts_from_pre_state(rpc_url, &mut fuzz_host, crypo_corpus.as_str());
+ }
+
let mut evm_executor: EVMQueueExecutor = EVMExecutor::new(fuzz_host, deployer);
if config.replay_file.is_some() {
@@ -340,7 +350,19 @@ pub fn evm_fuzzer(
let mut stages = tuple_list!(std_stage, concolic_stage, coverage_obs_stage);
- let mut executor = FuzzExecutor::new(evm_executor_ref.clone(), tuple_list!(jmp_observer));
+ let mut executor: FuzzExecutor<
+ EVMState,
+ EVMAddress,
+ Bytecode,
+ Bytes,
+ EVMAddress,
+ EVMU256,
+ Vec,
+ EVMInput,
+ EVMFuzzState,
+ (StdMapObserver, ()),
+ ConciseEVMInput,
+ > = FuzzExecutor::new(evm_executor_ref.clone(), tuple_list!(jmp_observer));
#[cfg(feature = "deployer_is_attacker")]
state.add_caller(&deployer);
@@ -464,6 +486,7 @@ pub fn evm_fuzzer(
ConciseEVMInput,
EVMQueueExecutor,
> = OracleFeedback::new(&mut oracles, &mut producers, evm_executor_ref.clone());
+
let wrapped_feedback = ConcolicFeedbackWrapper::new(Sha3WrappedFeedback::new(
feedback,
sha3_taint,
@@ -529,6 +552,30 @@ pub fn evm_fuzzer(
};
}
+ // add
+ // generate vm_state
+ if config.load_crypo_corpus.is_some() {
+ let rpc_url = "https://lb.nodies.app/v1/181a5ebf4c954f8496ae7cbc1ac8d03b";
+ let crypo_corpus = config.load_crypo_corpus.unwrap();
+
+ let testcases = OffchainCorpus::generate_testcases_sync(rpc_url, crypo_corpus.as_str());
+
+ for testcase in testcases {
+ let mut vm_state = OffchainCorpus::generate_vm_state_from_pre_state(&testcase);
+ for txn in testcase.0 {
+ load_code!(txn);
+ let (inp, call_until) = txn.to_input(vm_state.clone());
+ unsafe {
+ CALL_UNTIL = call_until;
+ }
+ fuzzer
+ .evaluate_input_events(state, &mut executor, &mut mgr, inp, false)
+ .unwrap();
+ vm_state = state.get_execution_result().new_state.clone();
+ }
+ }
+ }
+
match config.replay_file {
None => {
// load initial corpus
diff --git a/tests/evm_manual/foundry1/test/CreateOpcode.sol b/tests/evm_manual/foundry1/test/CreateOpcode.sol
new file mode 100644
index 000000000..1b00cf755
--- /dev/null
+++ b/tests/evm_manual/foundry1/test/CreateOpcode.sol
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: UNLICENSED
+pragma solidity ^0.8.0;
+import "solidity_utils/lib.sol";
+
+contract SOL {
+ Test public tt;
+ function setUp() public {
+ tt = new Test();
+ }
+
+ function test() public returns (uint) {
+ address account = address(tt);
+ uint size;
+ assembly {
+ size := extcodesize(account)
+ }
+ if (size > 65) {
+ bug();
+ }
+ return size;
+ }
+}
+
+contract Test {
+
+}
diff --git a/tests/init_cryo_corpus/ethereum__traces__18000000_to_18000000.parquet b/tests/init_cryo_corpus/ethereum__traces__18000000_to_18000000.parquet
new file mode 100644
index 0000000000000000000000000000000000000000..68dacd41487b27231a130645bb2c13b58d537303
GIT binary patch
literal 473087
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