diff --git a/.gitignore b/.gitignore index 145fd3e..f2ad452 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,7 @@ /target .z3-trace *.txt.log* -.idea/* \ No newline at end of file +.idea/* +*.hex +*.evm +*.txt \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..518bb94 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test-contracts/lib/forge-std"] + path = test-contracts/lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/Cargo.lock b/Cargo.lock index 5398a74..5b6e96c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,35 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -20,29 +49,86 @@ dependencies = [ "winapi", ] +[[package]] +name = "anyhow" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + [[package]] name = "arrayvec" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "ascii-canvas" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +dependencies = [ + "term", +] + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] +[[package]] +name = "auto_impl" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a8c1df849285fbacd587de7818cc7d13be6cd2cbcd47a04fb1801b0e2706e33" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 1.0.107", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bindgen" version = "0.58.1" @@ -52,7 +138,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "clap", + "clap 2.34.0", "env_logger", "lazy_static", "lazycell", @@ -66,6 +152,21 @@ dependencies = [ "which", ] +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bitflags" version = "1.3.2" @@ -84,6 +185,36 @@ 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.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + +[[package]] +name = "build_const" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + [[package]] name = "byte-slice-cast" version = "1.2.2" @@ -96,11 +227,44 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +dependencies = [ + "serde", +] + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "cc" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +dependencies = [ + "jobserver", +] [[package]] name = "cexpr" @@ -117,6 +281,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "cipher" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" +dependencies = [ + "generic-array", +] + [[package]] name = "clang-sys" version = "1.4.0" @@ -137,491 +320,2612 @@ dependencies = [ "ansi_term", "atty", "bitflags", - "strsim", - "textwrap", + "strsim 0.8.0", + "textwrap 0.11.0", "unicode-width", "vec_map", ] [[package]] -name = "cmake" -version = "0.1.49" +name = "clap" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ - "cc", + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim 0.10.0", + "termcolor", + "textwrap 0.16.0", ] [[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "derive_more" -version = "0.99.17" +name = "clap_derive" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ - "convert_case", + "heck", + "proc-macro-error", "proc-macro2", "quote", - "rustc_version", - "syn", + "syn 1.0.107", ] [[package]] -name = "env_logger" -version = "0.8.4" +name = "clap_lex" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "os_str_bytes", ] [[package]] -name = "fixed-hash" -version = "0.8.0" +name = "cmake" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" +checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", + "cc", ] [[package]] -name = "funty" -version = "2.0.0" +name = "console" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "unicode-width", + "winapi", +] [[package]] -name = "getrandom" -version = "0.2.8" +name = "console" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ - "cfg-if", + "encode_unicode", + "lazy_static", "libc", - "wasi", + "windows-sys 0.42.0", ] [[package]] -name = "glob" -version = "0.3.1" +name = "const-oid" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" [[package]] -name = "hashbrown" -version = "0.12.3" +name = "constant_time_eq" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] -name = "hex" -version = "0.4.3" +name = "cpufeatures" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] [[package]] -name = "humantime" -version = "2.1.0" +name = "crc32fast" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] [[package]] -name = "impl-codec" -version = "0.6.0" +name = "crossbeam-channel" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" dependencies = [ - "parity-scale-codec", + "cfg-if", + "crossbeam-utils", ] [[package]] -name = "impl-trait-for-tuples" -version = "0.2.2" +name = "crossbeam-deque" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ - "proc-macro2", - "quote", - "syn", + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "indexmap" -version = "1.9.2" +name = "crossbeam-epoch" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", - "hashbrown", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "crossbeam-utils" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +dependencies = [ + "cfg-if", +] [[package]] -name = "lazycell" -version = "1.3.0" +name = "crunchy" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] -name = "libc" -version = "0.2.139" +name = "crypto-bigint" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] [[package]] -name = "libloading" -version = "0.7.4" +name = "crypto-bigint" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "7c2538c4e68e52548bacb3e83ac549f903d44f011ac9d5abb5e132e67d0808f7" dependencies = [ - "cfg-if", - "winapi", + "generic-array", + "rand_core", + "subtle", + "zeroize", ] [[package]] -name = "log" -version = "0.4.17" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "cfg-if", + "generic-array", + "typenum", ] [[package]] -name = "memchr" -version = "2.5.0" +name = "der" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", +] [[package]] -name = "nom" -version = "5.1.2" +name = "der" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "19c5cb402c5c958281c7c0702edea7b780d03b86b606497ca3a10fcd3fc393ac" dependencies = [ - "memchr", - "version_check", + "const-oid", + "zeroize", ] [[package]] -name = "nom8" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "memchr", + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 1.0.107", ] [[package]] -name = "once_cell" -version = "1.17.0" +name = "dialoguer" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "c9dd058f8b65922819fabb4a41e7d1964e56344042c26efbccd465202c23fa0c" +dependencies = [ + "console 0.14.1", + "lazy_static", + "tempfile", + "zeroize", +] [[package]] -name = "parity-scale-codec" -version = "3.3.0" +name = "diff" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3840933452adf7b3b9145e27086a5a3376c619dca1a21b1e5a5af0d54979bed" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", + "generic-array", ] [[package]] -name = "parity-scale-codec-derive" -version = "3.1.4" +name = "digest" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", + "block-buffer 0.10.3", + "const-oid", + "crypto-common", + "subtle", ] [[package]] -name = "peeking_take_while" +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] [[package]] -name = "ppv-lite86" -version = "0.2.17" +name = "dunce" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c" [[package]] -name = "primitive-types" -version = "0.12.1" +name = "ecdsa" +version = "0.14.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" dependencies = [ - "fixed-hash", - "impl-codec", - "uint", + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", ] [[package]] -name = "proc-macro-crate" -version = "1.3.0" +name = "ecdsa" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +checksum = "106401dadc137d05cb0d4ab4d42be089746aefdfe8992df4d0edcf351c16ddca" dependencies = [ - "once_cell", - "toml_edit", + "der 0.7.2", + "digest 0.10.6", + "elliptic-curve 0.13.3", + "rfc6979 0.4.0", + "signature 2.1.0", ] [[package]] -name = "proc-macro2" -version = "1.0.50" +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" dependencies = [ - "unicode-ident", + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.6", + "ff 0.12.1", + "generic-array", + "group 0.12.1", + "rand_core", + "sec1 0.3.0", + "subtle", + "zeroize", ] [[package]] -name = "quote" -version = "1.0.23" +name = "elliptic-curve" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "22cdacd4d6ed3f9b98680b679c0e52a823b8a2c7a97358d508fe247f2180c282" dependencies = [ - "proc-macro2", + "base16ct 0.2.0", + "crypto-bigint 0.5.1", + "digest 0.10.6", + "ff 0.13.0", + "generic-array", + "group 0.13.0", + "pkcs8", + "rand_core", + "sec1 0.7.1", + "subtle", + "zeroize", ] [[package]] -name = "radium" -version = "0.7.0" +name = "ena" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +dependencies = [ + "log", +] [[package]] -name = "rand" -version = "0.8.5" +name = "encode_unicode" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ - "libc", - "rand_chacha", - "rand_core", + "cfg-if", ] [[package]] -name = "rand_chacha" -version = "0.3.1" +name = "env_logger" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ - "ppv-lite86", - "rand_core", + "atty", + "humantime", + "log", + "regex", + "termcolor", ] [[package]] -name = "rand_core" -version = "0.6.4" +name = "errno" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" dependencies = [ - "getrandom", + "errno-dragonfly", + "libc", + "windows-sys 0.45.0", ] [[package]] -name = "regex" -version = "1.7.1" +name = "errno-dragonfly" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", + "cc", + "libc", ] [[package]] -name = "regex-syntax" -version = "0.6.28" +name = "ethabi" +version = "18.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] [[package]] -name = "ruint" -version = "1.7.0" +name = "ethbloom" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad3a104dc8c3867f653b0fec89c65e00b0ceb752718ad282177a7e0f33257ac" +checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ - "derive_more", + "crunchy", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "tiny-keccak", +] + +[[package]] +name = "ethereum-types" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" +dependencies = [ + "ethbloom", + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", "primitive-types", - "ruint-macro", - "rustc_version", + "scale-info", + "uint", +] + +[[package]] +name = "ethers-core" +version = "2.0.2" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" +dependencies = [ + "arrayvec", + "bytes", + "chrono", + "elliptic-curve 0.13.3", + "ethabi", + "generic-array", + "getrandom", + "hex", + "k256 0.13.0", + "num_enum", + "open-fastrlp", + "rand", + "rlp", + "serde", + "serde_json", + "strum", + "tempfile", "thiserror", + "tiny-keccak", + "unicode-xid", ] [[package]] -name = "ruint-macro" -version = "1.0.2" +name = "ethers-solc" +version = "2.0.2" +source = "git+https://github.com/gakonst/ethers-rs#1dd35458695e2b967d4c2ff278cc8d0eaadcc9fb" +dependencies = [ + "cfg-if", + "dunce", + "ethers-core", + "futures-util", + "getrandom", + "glob", + "hex", + "home", + "md-5", + "num_cpus", + "once_cell", + "path-slash", + "rayon", + "regex", + "semver", + "serde", + "serde_json", + "sha2 0.10.6", + "solang-parser", + "svm-rs", + "svm-rs-builds", + "thiserror", + "tiny-keccak", + "tokio", + "tracing", + "walkdir", + "yansi", +] + +[[package]] +name = "fastrand" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62cc5760263ea229d367e7dff3c0cbf09e4797a125bd87059a6c095804f3b2d1" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] [[package]] -name = "rustc-hash" -version = "1.1.0" +name = "ff" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core", + "subtle", +] [[package]] -name = "rustc-hex" -version = "2.1.0" +name = "ff" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] [[package]] -name = "rustc_version" -version = "0.4.0" +name = "fixed-hash" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" dependencies = [ - "semver", + "byteorder", + "rand", + "rustc-hex", + "static_assertions", ] [[package]] -name = "semver" -version = "1.0.16" +name = "fixedbitset" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" [[package]] -name = "ser" -version = "0.1.0" +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ - "hex", - "once_cell", - "rand", - "ruint", - "smallvec", - "uuid", - "z3", + "crc32fast", + "miniz_oxide", ] [[package]] -name = "serde" -version = "1.0.152" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "shlex" +name = "form_urlencoded" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] [[package]] -name = "smallvec" -version = "1.10.0" +name = "fs2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.0", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", + "serde", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "home" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408" +dependencies = [ + "winapi", +] + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" +dependencies = [ + "http", + "hyper", + "rustls", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "idna" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "impl-codec" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" +dependencies = [ + "parity-scale-codec", +] + +[[package]] +name = "impl-rlp" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" +dependencies = [ + "rlp", +] + +[[package]] +name = "impl-serde" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indicatif" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b" +dependencies = [ + "console 0.15.5", + "lazy_static", + "number_prefix", + "regex", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnet" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" + +[[package]] +name = "is-terminal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" +dependencies = [ + "hermit-abi 0.3.1", + "io-lifetimes", + "rustix", + "windows-sys 0.48.0", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "jobserver" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.6", + "sha3", +] + +[[package]] +name = "k256" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955890845095ccf31ef83ad41a05aabb4d8cc23dc3cac5a9f5c89cf26dd0da75" +dependencies = [ + "cfg-if", + "ecdsa 0.16.4", + "elliptic-curve 0.13.3", + "once_cell", + "sha2 0.10.6", +] + +[[package]] +name = "keccak" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lalrpop" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f34313ec00c2eb5c3c87ca6732ea02dcf3af99c3ff7a8fb622ffb99c9d860a87" +dependencies = [ + "ascii-canvas", + "bit-set", + "diff", + "ena", + "is-terminal", + "itertools", + "lalrpop-util", + "petgraph", + "pico-args", + "regex", + "regex-syntax", + "string_cache", + "term", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "lalrpop-util" +version = "0.19.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5c1f7869c94d214466c5fd432dfed12c379fd87786768d36455892d46b18edd" +dependencies = [ + "regex", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" + +[[package]] +name = "lock_api" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "md-5" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.45.0", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" + +[[package]] +name = "nom" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +dependencies = [ + "memchr", + "version_check", +] + +[[package]] +name = "nom8" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" +dependencies = [ + "memchr", +] + +[[package]] +name = "num" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi 0.2.6", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d829733185c1ca374f17e52b762f24f535ec625d2cc1f070e34c8a9068f341b" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2be1598bf1c313dcdd12092e3f1920f463462525a21b7b4e11b4168353d0123e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] +name = "opaque-debug" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" + +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "os_str_bytes" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" + +[[package]] +name = "parity-scale-codec" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3840933452adf7b3b9145e27086a5a3376c619dca1a21b1e5a5af0d54979bed" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "windows-sys 0.45.0", +] + +[[package]] +name = "password-hash" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" +dependencies = [ + "base64ct", + "rand_core", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + +[[package]] +name = "path-slash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.6", + "hmac", + "password-hash", + "sha2 0.10.6", +] + +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + +[[package]] +name = "percent-encoding" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" + +[[package]] +name = "petgraph" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +dependencies = [ + "phf_macros", + "phf_shared 0.11.1", +] + +[[package]] +name = "phf_generator" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +dependencies = [ + "phf_shared 0.11.1", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92aacdc5f16768709a569e913f7451034034178b05bdc8acda226659a3dccc66" +dependencies = [ + "phf_generator", + "phf_shared 0.11.1", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + +[[package]] +name = "phf_shared" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pico-args" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8bcd96cb740d03149cbad5518db9fd87126a10ab519c011893b1754134c468" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.2", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "primitive-types" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +dependencies = [ + "fixed-hash", + "impl-codec", + "impl-rlp", + "impl-serde", + "scale-info", + "uint", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.107", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rayon" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +dependencies = [ + "getrandom", + "redox_syscall 0.2.16", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" + +[[package]] +name = "reqwest" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg", +] + +[[package]] +name = "revm" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73d84c8f9836efb0f5f5f8de4700a953c4e1f3119e5cfcb0aad8e5be73daf991" +dependencies = [ + "arrayref", + "auto_impl", + "bytes", + "hashbrown 0.13.2", + "hex", + "num_enum", + "primitive-types", + "revm_precompiles", + "rlp", + "serde", + "sha3", +] + +[[package]] +name = "revm_precompiles" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0353d456ef3e989dc9190f42c6020f09bc2025930c37895826029304413204b5" +dependencies = [ + "bytes", + "hashbrown 0.13.2", + "k256 0.11.6", + "num", + "once_cell", + "primitive-types", + "ripemd", + "sha2 0.10.6", + "sha3", + "substrate-bn", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.6", +] + +[[package]] +name = "rlp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +dependencies = [ + "bytes", + "rlp-derive", + "rustc-hex", +] + +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "ruint" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad3a104dc8c3867f653b0fec89c65e00b0ceb752718ad282177a7e0f33257ac" +dependencies = [ + "derive_more", + "primitive-types", + "rlp", + "ruint-macro", + "rustc_version", + "serde", + "thiserror", +] + +[[package]] +name = "ruint-macro" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cc5760263ea229d367e7dff3c0cbf09e4797a125bd87059a6c095804f3b2d1" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b24138615de35e32031d041a09032ef3487a616d901ca4db224e7d557efae2" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +dependencies = [ + "base64", +] + +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scale-info" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cfdffd972d76b22f3d7f81c8be34b2296afd3a25e0a547bd9abe340a4dbbe97" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61fa974aea2d63dd18a4ec3a49d59af9f34178c73a4f56d2f18205628d00681e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48518a2b5775ba8ca5b46596aae011caa431e6ce7e4a67ead66d92f08884220e" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.2", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" +dependencies = [ + "serde", +] + +[[package]] +name = "ser" +version = "0.1.0" +dependencies = [ + "ethers-solc", + "hex", + "once_cell", + "paste", + "rand", + "revm", + "rlp", + "ruint", + "serde", + "smallvec", + "uuid", + "z3", +] + +[[package]] +name = "serde" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.13", +] + +[[package]] +name = "serde_json" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + +[[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.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + +[[package]] +name = "sha3" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +dependencies = [ + "digest 0.10.6", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.6", + "rand_core", +] + +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.6", + "rand_core", +] + +[[package]] +name = "siphasher" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "solang-parser" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff87dae6cdccacdbf3b19e99b271083556e808de0f59c74a01482f64fdbc61fc" +dependencies = [ + "itertools", + "lalrpop", + "lalrpop-util", + "phf", + "unicode-xid", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e" +dependencies = [ + "base64ct", + "der 0.7.2", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", +] + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "strum" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 1.0.107", +] + +[[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", + "rustc-hex", +] + +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + +[[package]] +name = "svm-rs" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01afefe60c02f4a2271fb15d1965c37856712cebb338330b06649d12afec42df" +dependencies = [ + "anyhow", + "cfg-if", + "clap 3.2.23", + "console 0.14.1", + "dialoguer", + "fs2", + "hex", + "home", + "indicatif", + "itertools", + "once_cell", + "rand", + "reqwest", + "semver", + "serde", + "serde_json", + "sha2 0.9.9", + "tempfile", + "thiserror", + "tokio", + "tracing", + "url", + "zip", +] + +[[package]] +name = "svm-rs-builds" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e69c19996b709c881de264a6ce64609ff305ef0bf59fc45243ac5a67291afd1" +dependencies = [ + "build_const", + "hex", + "semver", + "serde_json", + "svm-rs", +] + +[[package]] +name = "syn" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "terminal_size" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" + +[[package]] +name = "thiserror" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "time" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +dependencies = [ + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] -name = "strsim" -version = "0.8.0" +name = "tiny-keccak" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] [[package]] -name = "syn" -version = "1.0.107" +name = "tinyvec" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "tinyvec_macros", ] [[package]] -name = "tap" -version = "1.0.1" +name = "tinyvec_macros" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] -name = "termcolor" -version = "1.2.0" +name = "tokio" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ - "winapi-util", + "autocfg", + "bytes", + "libc", + "memchr", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.45.0", ] [[package]] -name = "textwrap" -version = "0.11.0" +name = "tokio-macros" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "unicode-width", + "proc-macro2", + "quote", + "syn 1.0.107", ] [[package]] -name = "thiserror" -version = "1.0.38" +name = "tokio-rustls" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ - "thiserror-impl", + "rustls", + "tokio", + "webpki", ] [[package]] -name = "thiserror-impl" -version = "1.0.38" +name = "tokio-util" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] [[package]] @@ -641,6 +2945,56 @@ dependencies = [ "toml_datetime", ] +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", +] + +[[package]] +name = "tracing-core" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + [[package]] name = "uint" version = "0.9.5" @@ -653,18 +3007,56 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unicode-bidi" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" + [[package]] name = "unicode-ident" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-width" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "url" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.2.2" @@ -686,12 +3078,127 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +dependencies = [ + "log", + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 1.0.107", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.107", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + +[[package]] +name = "web-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + [[package]] name = "which" version = "3.1.1" @@ -732,6 +3239,162 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi", +] + [[package]] name = "wyz" version = "0.5.1" @@ -741,6 +3404,12 @@ dependencies = [ "tap", ] +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" + [[package]] name = "z3" version = "0.11.2" @@ -761,3 +3430,59 @@ dependencies = [ "bindgen", "cmake", ] + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" + +[[package]] +name = "zip" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef" +dependencies = [ + "aes", + "byteorder", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "flate2", + "hmac", + "pbkdf2", + "sha1", + "time", + "zstd", +] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.8+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c" +dependencies = [ + "cc", + "libc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index cf8b92c..094fefa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,13 +8,22 @@ edition = "2021" [dependencies] once_cell = "1.16.0" -ruint = { version = "1.7.0", features = ["primitive-types"] } +ruint = { version = "1.7.0", features = ["primitive-types", "rlp", "serde"] } uuid = { version = "1.2.2", features = ["v4"] } hex = "0.4.3" smallvec = "1.10.0" rand = "0.8.5" - - +revm = { version = "2.3", default-features = false, features = [ + "std", + "k256", + "with-serde", + "memory_limit", + "optional_eip3607" +] } +ethers-solc = { git = "https://github.com/gakonst/ethers-rs", features = ["full"]} +paste = "1.0.12" +rlp = "0.5.2" +serde = "1.0.164" [target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies] z3 = {version = "0.11.2", features = ["static-link-z3"]} diff --git a/README.md b/README.md index 0c8feab..d808bc7 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Ser also differs from most symbolic EVM tools in that state transitions in the E The tradeoff is that this approach - as it is currently implemented - uses more memory than if the execution of each instruction and its effect on the machine state were coupled together. -See this [example output](/example-trace.txt) of the type of trace tree generated by Ser. +See this [example output](/example-trace.md) of the type of trace tree generated by Ser. ### Acknowledgements Special thanks to [Arnur Sabet](https://github.com/arnursabet) for his contributions to an earlier prototype of this software. \ No newline at end of file diff --git a/example-trace.txt b/example-trace.md similarity index 99% rename from example-trace.txt rename to example-trace.md index f270726..f78060b 100644 --- a/example-trace.txt +++ b/example-trace.md @@ -1,6 +1,6 @@ ----- machine::machine_returns_one_exec_for_non_branching_pgm stdout ---- +``` ------- Reachable State --------- State EvmState { memory: Memory { @@ -1021,4 +1021,5 @@ StateTree { }, ), right: None, -} \ No newline at end of file +} +``` diff --git a/examples/simple_pgm.rs b/examples/simple_pgm.rs new file mode 100644 index 0000000..a704963 --- /dev/null +++ b/examples/simple_pgm.rs @@ -0,0 +1,29 @@ +#![allow(unused_imports)] +use ser::{ + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, +}; +use z3::ast::*; + +pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; +fn main() { + let pgm = Parser::with_pgm(SUPERSIMPLE).parse(); + let mut evm = Evm::new(pgm); + + let execution_trace = evm.exec(); + { + let leaf = execution_trace.states.leaves(); + assert_eq!(1, leaf.len()); + let final_tree = leaf.first().unwrap().clone(); + + let mut mem_val = final_tree.val.mem_read(bvi(0)); + mem_val.simplify(); + assert_eq!(bvi(66), mem_val); + } + + let tree_flattened = execution_trace.states.into_iter().collect::>(); + eprintln!( + "Nodes in tree: {}\nTree Nodes: {:#?}", + tree_flattened.len(), + tree_flattened + ); +} diff --git a/examples/simple_storage.rs b/examples/simple_storage.rs new file mode 100644 index 0000000..8aa74a9 --- /dev/null +++ b/examples/simple_storage.rs @@ -0,0 +1,34 @@ +#![allow(unused_imports, unused)] +use ser::{ + bvc, bvi, conversion::*, instruction::Instruction, machine::*, memory::*, parser::*, stack::*, + storage::*, traits::*, +}; +use z3::ast::*; + +pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; + +fn main() { + let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); + + let mut evm = Evm::new(pgm); + + let execution = evm.exec(); + { + let leaf = execution.states.leaves(); + // as seen here https://bytegraph.xyz/bytecode/e5987a6f24f8af926faddae88de7980f/graph + assert_eq!(7, leaf.len()); + } + + let reachability_report = Evm::exec_check(execution); + println!("Report: {:#?}", reachability_report); + let traces = reachability_report + .iter() + .map(|trace| trace.0.iter().map(|t| &t.1).collect::>()) + .collect::>(); + println!("traces: {:#?}", traces); + let reverted_traces = traces + .into_iter() + .filter(|t| *t.last().unwrap().clone() == Instruction::Revert) + .collect::>(); + println!("TRACES WITH REVERTS {:#?}", reverted_traces); +} diff --git a/examples/swaps.rs b/examples/swaps.rs new file mode 100644 index 0000000..929904d --- /dev/null +++ b/examples/swaps.rs @@ -0,0 +1,71 @@ +#![allow(unused_imports, unused)] +use ser::{ + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, +}; +use z3::{ast::*, SatResult}; +/* +SHOULD REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +SWAP2 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0 +RETURN + + +SHOULD NOT REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +PUSH1 0x40 +SWAP3 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0x10 +RETURN + + +MAYBE REVERT: +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +PUSH1 0x0d +JUMPI +REVERT +JUMPDEST +PUSH1 0x00 +RETURN + +*/ +const SWAP2_JUMPI_REVERT: &str = r#"604260006150003691600d57fd5b6000f3"#; +const SWAP2_JUMPI_MAYBE_REVERT: &str = r#"6042600061500036600d57fd5b6000f3"#; +const SWAP3_JUMPI_RETURN_16: &str = r#"60426000615000604091600e57fd5b6000f3"#; +fn main() { + let pgm = Parser::with_pgm(SWAP2_JUMPI_MAYBE_REVERT).parse(); + let mut evm = Evm::new(pgm); + let execution = evm.exec(); + //eprintln!("Execution tree: {:#?}", execution.states.clone()); + // Should have two paths: both reachable. The first reachable path is the one in which calldata is zero and there is a revert. + // The second reachable path is the one in which calldata is not zero and there is not a revert. + let reachability_report = Evm::exec_check(execution); + assert_eq!(2, reachability_report.len()); + eprintln!("REPORT: {:#?}", reachability_report); + assert_eq!( + SatResult::Sat, + reachability_report.first().unwrap().1.unwrap() + ); + assert_eq!( + SatResult::Sat, + reachability_report.get(1).unwrap().1.unwrap() + ); +} diff --git a/src/conversion/mod.rs b/src/conversion/mod.rs new file mode 100644 index 0000000..f4b39df --- /dev/null +++ b/src/conversion/mod.rs @@ -0,0 +1,180 @@ +use std::cmp::Ordering; + +use crate::{ + bvc, bvi, bvi_8byte, ctx, + instruction::{push32, Instruction}, + parser::zero_extend, + record::push, + BVType, BitVec, BV, +}; +use rlp::{Decodable, Encodable}; +use ruint::{uint, Bits, FromUintError, ToUintError, Uint}; +use serde::{Deserialize, Serialize}; +use z3_ext::{ast::Ast, Context}; + +impl From> for BitVec<32> { + fn from(value: Uint<256, 4>) -> Self { + let mut bv: BV<'static> = BV::from_u64(ctx(), 0, 8); + let bytes: [u8; 32] = value.clone().to_be_bytes(); + + for i in bytes.iter() { + let new_bv: BV<'static> = bvi::<1>(*i).into(); + bv = bv.concat(&new_bv).simplify(); + } + bv.extract(256 - 8 - 1, 0).simplify().into() + } +} + +impl From> for Uint<256, 4> { + fn from(value: BitVec<32>) -> Self { + let value: BV<'static> = value.as_ref().clone(); + let mut numbits = [0u8; 32]; + + for i in (0..32_u32) { + let offset = 256 - (i * 8) - 1; + let byte_extract: BV<'static> = value.extract(offset, offset - 7).simplify(); + // since byte_extract is a single byte, downcasting to u8 will not change the number + let byte = byte_extract.as_u64().unwrap() as u8; + numbits[i as usize] = byte; + } + Bits::from_be_bytes(numbits).as_uint().clone() + } +} + +impl From> for BitVec { + fn from(bv: BV<'static>) -> Self { + let bit_sz = SZ * 8; + let bvsz = bv.get_size(); + let bv = match bvsz.cmp(&(bit_sz as u32)) { + Ordering::Less => bv.zero_ext((bit_sz - bvsz as usize) as u32), + Ordering::Equal => bv, + Ordering::Greater => bv.extract(bit_sz as u32, 0), + }; + // let bv = if bvsz < bit_sz { + // bv.zero_ext(bit_sz - bvsz) + // } else if bvsz > bit_sz { + // bv.extract(bit_sz, 0) + // } else { + // bv + // }; + Self { + inner: BVType::Z3(bv), + typ: Default::default(), + } + } +} + +impl From> for BV<'static> { + fn from(bv: BitVec) -> Self { + match bv.inner { + BVType::Z3(bv) => bv, + _ => panic!("Should never happen"), + } + } +} + +impl From<[u8; SZ]> for BitVec { + fn from(value: [u8; SZ]) -> Self { + let ctx: &'static Context = ctx(); + let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); + + for i in value.iter() { + let new_bv: BV<'static> = bvi::<1>(*i).into(); + bv = bv.concat(&new_bv).simplify(); + } + // eprintln!("VALUE CONVERTING FROM: {:#x?}", value); + // eprintln!("BV IN SLICE CONVERT: {:#?} SIZE: {}", bv, bv.get_size()); + bv.extract((bv.get_size() - 8 - 1) as u32, 0) + .simplify() + .into() + } +} + +pub fn bitvec_array_to_bv<'ctx>(value: Vec>) -> BV<'ctx> { + let ctx: &'static Context = ctx(); + let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); + for i in value.iter() { + bv = bv.concat(i.as_ref()).simplify(); + } + bv.extract((bv.get_size() - 8 - 1) as u32, 0).simplify() +} +impl TryFrom>> for BitVec { + type Error = String; + + fn try_from(value: Vec>) -> Result { + let ctx: &'static Context = ctx(); + let mut bv: BV<'static> = BV::from_u64(ctx, 0, 8); + for i in value.iter() { + bv = bv.concat(i.as_ref()).simplify(); + } + Ok(bv + .extract((bv.get_size() - 8 - 1) as u32, 0) + .simplify() + .into()) + } +} +impl AsRef> for BitVec { + fn as_ref(&self) -> &BV<'static> { + match &self.inner { + BVType::Z3(bv) => bv, + _ => panic!("Should never happen"), + } + } +} + +#[cfg(test)] +fn push_arg_to_push(arg: &[u8]) -> Instruction { + let slice_full = zero_extend::<32>(&arg).into(); + push32(slice_full) +} + +#[test] +fn test_slice_to_op_arg() { + let mut slice8 = 327000_u64.to_be_bytes(); + let inst = push_arg_to_push(&slice8); +} +#[test] +fn test_slice_to_bitvec() { + let mut slice8 = 327000_u64.to_be_bytes(); + + let slice_full = zero_extend::<32>(&slice8); + let bv: BitVec<32> = slice_full.into(); + + let num = uint!(0x000000000000000000000000000000000000000000000000000000000004FD58_U256); + let bv_as_num: Uint<256, 4> = bv.into(); + assert_eq!(num, bv_as_num); +} + +#[test] +fn test_u256_to_bytes() { + let num = uint!(0xc85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4_U256); + + let mut buf = [0u8; 32]; + + let bytes: [u8; 32] = num.to_be_bytes(); + + let numbit: Bits<256, 4> = Bits::from_be_bytes(bytes); + let newnum: Uint<256, 4> = numbit.as_uint().clone(); + assert_eq!(num, newnum); +} + +#[test] +fn test_to_bv() { + let num = uint!(0xc85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4_U256); + let mut bv: BitVec<32> = num.into(); + + let small_num = uint!(0x0000000000000000000000000000000000000000000000000000000000000009_U256); + let mut bv_2 = BitVec::from(small_num); + bv_2.simplify(); + let mut expected = bvi(9); + expected.simplify(); + assert_eq!(expected, bv_2); +} + +#[test] +fn test_from_bv() { + let bv = bvi(327000); + let num = uint!(0x000000000000000000000000000000000000000000000000000000000004FD58_U256); + let bv_to_num: Uint<256, 4> = bv.into(); + assert_eq!(num, bv_to_num); +} diff --git a/src/exec/mod.rs b/src/exec/mod.rs new file mode 100644 index 0000000..cf7959b --- /dev/null +++ b/src/exec/mod.rs @@ -0,0 +1,212 @@ +use uuid::Uuid; + +use crate::parser::Program; +use crate::state::evm::EvmState; +use crate::state::tree::*; +use crate::{ + instruction::Instruction, + record::MachineRecord, + traits::{MachineComponent, MachineInstruction, MachineState}, +}; + +#[derive(Default, Debug)] +pub struct Execution<'ctx> { + changes: Vec>, + program: Program, + pub states: StateTree<'ctx>, +} + +#[derive(Default, Debug)] +pub struct StepRecord { + left_insert: Option, + right_insert: Option, + halted_left: bool, + halted_right: bool, +} + +impl StepRecord { + pub fn new(halted_left: bool, halted_right: bool) -> Self { + Self { + halted_left, + halted_right, + ..Default::default() + } + } + pub fn halted_left(&self) -> bool { + self.halted_left + } + + pub fn halted_right(&self) -> bool { + self.halted_right + } + pub fn branched(&self) -> bool { + self.left_insert.is_some() && self.right_insert.is_some() + } + + pub fn left_id(&self) -> Option<&NodeId> { + self.left_insert.as_ref() + } + + pub fn right_id(&self) -> Option<&NodeId> { + self.right_insert.as_ref() + } + + pub fn set_left(mut self, left: NodeId) -> Self { + self.left_insert = Some(left); + self + } + pub fn set_right(mut self, right: NodeId) -> Self { + self.right_insert = Some(right); + self + } +} + +impl<'ctx> Execution<'ctx> { + pub fn new(start_state: EvmState, pgm: Program) -> Self { + Self { + program: pgm, + states: StateTree::from((start_state, None)), + ..Default::default() + } + } + + // Returns the StepRecord AND updates the Exec state tree + pub fn step_mut(&mut self) -> StepRecord { + // bool returns if there is a branch + let curr_state_id = self.states.id.clone(); + let mut curr_state = self.states.val.clone(); + let curr_inst = curr_state.curr_instruction(); + let curr_pc = curr_state.pc(); + let change_rec = curr_inst.exec(&curr_state); + eprintln!("CHANGE REC IN EXEC: {:#?}", change_rec); + let is_branch = change_rec.constraints.is_some(); + if is_branch { + eprintln!( + "IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", + change_rec, curr_pc + ); + } + curr_state.apply_change(change_rec.clone()); + let mut report = StepRecord::new(false, change_rec.halt); + if is_branch { + // then curr_state.apply generated the right branching state; thus, a state tree w/ + // an additional constraint + // and left tree (by convention left path represents straight line execution) is the negation of such constraint + let mut left_state = curr_state.clone(); + left_state.set_pc(curr_pc + 1); + if !left_state.can_continue() { + report.halted_left = true; + } + + let left_tree = StateTree::from(( + left_state.clone(), + change_rec.constraints.clone().unwrap().not(), + )); + let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); + + let left_tree_ref = self.states.insert_left_of(left_tree, curr_state_id.id()); + + let right_tree_ref = self.states.insert_right_of(right_tree, curr_state_id.id()); + + report = report.set_left(left_tree_ref); + report.set_right(right_tree_ref) + } else { + let left_tree = StateTree::from((curr_state, None)); + let left_id = self.states.insert_left_of(left_tree, curr_state_id.id()); + + report.set_left(left_id) + } + } + + // Returns the step record but does not mutate the Exec state tree + pub fn step(&self) -> StepRecord { + // bool returns if there is a branch + let curr_state_id = self.states.id.clone(); + let mut curr_state = self.states.val.clone(); + let curr_inst = curr_state.curr_instruction(); + let curr_pc = curr_state.pc(); + let change_rec = curr_inst.exec(&curr_state); + + let is_branch = change_rec.constraints.is_some(); + curr_state.apply_change(change_rec.clone()); + let mut report = StepRecord::new(false, change_rec.halt); + if is_branch { + // then curr_state.apply generated the right branching state; thus, a state tree w/ + // an additional constraint + // and left tree (by convention left path represents straight line execution) is the negation of such constraint + let mut left_state = curr_state.clone(); + left_state.set_pc(curr_pc + 1); + if !left_state.can_continue() { + report.halted_left = true; + } + let left_tree = StateTree::from(( + left_state.clone(), + change_rec.constraints.clone().unwrap().not(), + )); + let right_tree = StateTree::from((left_state, change_rec.constraints.unwrap())); + + report + .set_left(left_tree.id.clone()) + .set_right(right_tree.id.clone()) + } else { + let left_tree = StateTree::from((curr_state, None)); + + report.set_left(left_tree.id.clone()) + } + } + + pub fn step_from_mut(&mut self, node_id: &NodeId) -> StepRecord { + let curr_state_id = node_id.clone(); + let mut curr_state_tree = self.states.find_by_id(node_id).unwrap().clone(); + let mut curr_state = &mut curr_state_tree.val; + if !curr_state.can_continue() { + return StepRecord::new(true, true); + } + + let curr_inst = curr_state.curr_instruction(); + let curr_pc = curr_state.pc(); + //eprintln!("CURR STATE IN STEP FROM MUT: {:#?}", curr_state); + let change_rec = curr_inst.exec(&curr_state); + eprintln!("CHANGE REC IN STEP: {:#?}", change_rec); + + let is_branch = change_rec.constraints.is_some(); + curr_state.apply_change(change_rec.clone()); + if is_branch { + eprintln!( + "IS BRANCH HERE:\nChange record {:#?}\nCurr_state pc: {}", + change_rec, curr_pc + ); + } + if change_rec.halt { + eprintln!("Halt occurred here: {:#?}", change_rec); + } + let curr_state = curr_state; + let mut report = StepRecord::new(false, change_rec.halt); + // assert_eq!(change_rec.halt, curr_state.halt); + if is_branch { + // then curr_state.apply generated the right branching state; thus, a state tree w/ + // an additional constraint + // and left tree (by convention left path represents straight line execution) is the negation of such constraint + let mut left_state = curr_state.clone(); + let right_tree = + StateTree::from((left_state.clone(), change_rec.constraints.clone().unwrap())); + left_state.set_pc(curr_pc + 1); + report.halted_left = left_state.halt; + + let left_tree = StateTree::from((left_state, change_rec.constraints.unwrap().not())); + + let left_tree_ref = self.states.insert_left_of(left_tree, node_id.id()); + let right_tree_ref = self.states.insert_right_of(right_tree, node_id.id()); + // curr_state_tree.left = Some(Box::new(left_tree)); + // curr_state_tree.right = Some(Box::new(right_tree)); + + report.set_left(left_tree_ref).set_right(right_tree_ref) + } else { + let left_tree = StateTree::from((curr_state.clone(), None)); + let left_tree_ref = self.states.insert_left_of(left_tree, curr_state_id.id()); + //curr_state_tree.left = Some(Box::new(left_tree)); + + report.set_left(left_tree_ref) + } + } +} diff --git a/src/instruction/mod.rs b/src/instruction/mod.rs index d8d7f8a..1c96746 100644 --- a/src/instruction/mod.rs +++ b/src/instruction/mod.rs @@ -4,28 +4,24 @@ use std::ops::{BitAnd, BitOr, BitXor}; use ruint::aliases::U256; use z3_ext::ast::{Ast, Bool, BV}; -use crate::record::{push, MemChange, MemOp}; +use crate::conversion::bitvec_array_to_bv; +use crate::record::{push, MemChange, MemOp, StorageChange, StorageOp}; use crate::state::env::*; use crate::state::evm::EvmState; +use crate::storage::StorageValue; use crate::traits::*; use crate::{ bvi, machine::Evm, memory::Memory, + random_bv_arg, record::{Index, MachineRecord, StackChange, StackOp}, stack::Stack, }; use super::smt::*; -use rand::Rng; -pub fn random_bv_arg() -> BitVec<32> { - let mut rng = rand::thread_rng(); - let rand_num: u64 = rng.gen(); - BitVec::new_literal(rand_num) -} - -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Instruction { Stop, Add, @@ -33,11 +29,12 @@ pub enum Instruction { Sub, Div, SDiv, - SMod, Mod, + SMod, AddMod, MulMod, Exp, + SignExtend, Lt, Gt, Slt, @@ -182,14 +179,78 @@ fn exec_dup_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { pc: (mach.pc(), mach.pc() + 1), mem: Default::default(), halt: false, + storage: None, constraints: None, } } +fn exec_swap_nth(mach: &EvmState, n: usize) -> MachineRecord<32> { + MachineRecord { + stack: Some(StackChange { + pop_qty: 0, + push_qty: 0, + swap_depth: n, + ops: vec![], + }), + pc: (mach.pc(), mach.pc() + 1), + mem: Default::default(), + halt: false, + storage: None, + constraints: None, + } +} + +impl Instruction { + pub fn byte_size(&self) -> usize { + let inst_additional_size: usize = match self { + Instruction::Push1(_) => 1, + Instruction::Push2(_) => 2, + Instruction::Push3(_) => 3, + Instruction::Push4(_) => 4, + Instruction::Push5(_) => 5, + Instruction::Push6(_) => 6, + Instruction::Push7(_) => 7, + Instruction::Push8(_) => 8, + Instruction::Push9(_) => 9, + Instruction::Push10(_) => 10, + Instruction::Push11(_) => 11, + Instruction::Push12(_) => 12, + Instruction::Push13(_) => 13, + Instruction::Push14(_) => 14, + Instruction::Push15(_) => 15, + Instruction::Push16(_) => 16, + Instruction::Push17(_) => 17, + Instruction::Push18(_) => 18, + Instruction::Push19(_) => 19, + Instruction::Push20(_) => 20, + Instruction::Push21(_) => 21, + Instruction::Push22(_) => 22, + Instruction::Push23(_) => 23, + Instruction::Push24(_) => 24, + Instruction::Push25(_) => 25, + Instruction::Push26(_) => 26, + Instruction::Push27(_) => 27, + Instruction::Push28(_) => 28, + Instruction::Push29(_) => 29, + Instruction::Push30(_) => 30, + Instruction::Push31(_) => 31, + Instruction::Push32(_) => 32, + _ => 0, + }; + inst_additional_size + 1 + } +} impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { fn exec(&self, mach: &EvmState) -> MachineRecord<32> { match self { - Instruction::Stop => todo!(), + Instruction::Stop => MachineRecord { + halt: true, + stack: None, + mem: None, + constraints: None, + storage: None, + pc: (mach.pc(), mach.pc()), + }, Instruction::Add => { let stack = mach.stack(); let [stack_top, stack_top2] = stack.peek_top().unwrap(); @@ -203,14 +264,16 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack_change = StackChange { pop_qty: 2, push_qty: 1, + swap_depth: 0, ops: vec![stack_op_1, stack_op_2, stack_op_3], }; MachineRecord { stack: Some(stack_change), mem: Default::default(), - pc: (pc, pc + 1), + pc: (pc, pc + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Mul => { @@ -221,9 +284,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Sub => { @@ -234,9 +298,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Div => { @@ -247,9 +312,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::SDiv => { @@ -260,9 +326,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::SMod => { @@ -273,9 +340,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Mod => { @@ -286,9 +354,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::AddMod => { @@ -299,9 +368,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::MulMod => { @@ -312,9 +382,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Exp => { @@ -338,9 +409,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Lt => { @@ -357,9 +429,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Gt => { @@ -376,9 +449,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Slt => { @@ -395,9 +469,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Sgt => { @@ -414,9 +489,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Eq => { @@ -433,9 +509,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::And => { @@ -448,9 +525,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Or => { @@ -463,9 +541,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Xor => { @@ -478,9 +557,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Not => { @@ -494,9 +574,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Byte => todo!(), @@ -511,9 +592,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Shr => { @@ -527,18 +609,62 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } - Instruction::Sha3 => todo!(), - Instruction::Address => todo!(), + Instruction::Sha3 => { + let stack = mach.stack(); + let [offset, size] = stack.peek_top().unwrap(); + let mut offsett = offset.clone(); + let mut sizee = size.clone(); + offsett.simplify(); + sizee.simplify(); + + let mem = mach.mem().read_with_offset(offsett.clone(), sizee.clone()); + let sz = usize::from(sizee.clone()); + + let mut bv: BV<'static> = bitvec_array_to_bv(mem); + + let hashed = sha3(bv.get_size()).apply(&[&bv]); + + let hashed: BitVec<32> = hashed.as_bv().unwrap().into(); + let mem_change = MemChange { + ops_log: vec![MemOp::Read { + idx: offsett.clone(), + }], + }; + let stack_change = + StackChange::with_ops(vec![StackOp::Pop, StackOp::Pop, StackOp::Push(hashed)]); + + MachineRecord { + stack: Some(stack_change), + mem: Some(mem_change), + pc: (mach.pc(), mach.pc() + self.byte_size()), + constraints: None, + halt: false, + storage: None, + } + } + Instruction::Address => { + let addr = mach.address.as_ref(); + let addr = addr.zero_ext(12 * 8); + MachineRecord { + stack: Some(StackChange::with_ops(vec![StackOp::Push(addr.into())])), + mem: None, + pc: (mach.pc(), mach.pc() + self.byte_size()), + constraints: None, + halt: false, + storage: None, + } + }, Instruction::Balance => { let stack = mach.stack(); let addr = stack.peek().unwrap(); let bal = balance() - .apply(&[addr.as_ref(), random_bv_arg().as_ref()]) + .apply(&[addr.as_ref(), random_bv_arg::<32>().as_ref()]) .as_bv() .unwrap(); let stack_diff = StackChange::with_ops(vec![pop(), push(bal.into())]); @@ -546,9 +672,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Origin => { @@ -559,9 +686,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Caller => { @@ -572,22 +700,24 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::CallValue => { let stack = mach.stack(); let call_val = call_value().apply(&[]).as_bv().unwrap(); - let stack_diff = StackChange::with_ops(vec![pop(), push(call_val.into())]); + let stack_diff = StackChange::with_ops(vec![push(call_val.into())]); MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::CallDataLoad => { @@ -599,22 +729,24 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::CallDataSize => { let stack = mach.stack(); let call_data_sz = call_data_size().apply(&[]).as_bv().unwrap(); - let stack_diff = StackChange::with_ops(vec![pop(), push(call_data_sz.into())]); + let stack_diff = StackChange::with_ops(vec![push(call_data_sz.into())]); MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::CallDataCopy => todo!(), @@ -628,9 +760,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::ExtCodeSize => { @@ -642,9 +775,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::ExtCodeCopy => todo!(), @@ -659,9 +793,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Coinbase => { @@ -672,9 +807,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Timestamp => { @@ -685,9 +821,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::Number => todo!(), @@ -699,9 +836,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::GasLimit => { @@ -712,9 +850,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::ChainId => { @@ -725,9 +864,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(stack_diff), mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::SelfBalance => todo!(), @@ -736,20 +876,25 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let pc = mach.pc(); let stack_rec = StackChange { pop_qty: 1, + swap_depth: 0, push_qty: 0, ops: vec![StackOp::Pop], }; MachineRecord { stack: Some(stack_rec), - pc: (pc, pc + 1), + pc: (pc, pc + self.byte_size()), mem: Default::default(), constraints: None, halt: false, + storage: None, } } Instruction::MLoad => { let stack = mach.stack(); let dest = stack.peek().unwrap(); + let mut dest = dest.clone(); + dest.simplify(); + let mut val_mem = mach.memory.read_word(dest.clone()); val_mem.simplify(); @@ -760,8 +905,9 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(vec![pop(), push(val_mem)])), mem: Some(mem_change), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), halt: false, + storage: None, constraints: None, } } @@ -786,7 +932,8 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { stack: Some(stack_change), constraints: None, halt: false, - pc: (mach.pc(), mach.pc() + 1), + storage: None, + pc: (mach.pc(), mach.pc() + self.byte_size()), } } Instruction::MStore8 => { @@ -815,12 +962,79 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { stack: Some(stack_change), constraints: None, halt: false, - pc: (mach.pc(), mach.pc() + 1), + storage: None, + pc: (mach.pc(), mach.pc() + self.byte_size()), + } + } + Instruction::SLoad => { + let key = mach.stack().peek().unwrap(); + let storage = mach.storage_read(key); + let stack_op_1 = StackOp::Pop; + let StorageValue::BV(sval) = storage else { + panic!("Arrays not yet supported"); + }; + let stack_op_2 = StackOp::Push(sval); + let stack_change = StackChange::with_ops(vec![stack_op_1, stack_op_2]); + MachineRecord { + mem: None, + stack: Some(stack_change), + storage: Some(StorageChange { + log: vec![StorageOp::Read { + addr: mach.address.clone(), + idx: key.clone(), + }], + }), + pc: (mach.pc(), mach.pc() + self.byte_size()), + constraints: None, + halt: false, + } + } + Instruction::SStore => { + let key = mach.stack().peek().unwrap(); + let val = mach.stack().peek_nth(1).unwrap(); + + let stack_rec = StackChange { + pop_qty: 2, + push_qty: 0, + swap_depth: 0, + ops: vec![StackOp::Pop, StackOp::Pop], + }; + let storage_change = StorageChange { + log: vec![StorageOp::Write { + addr: mach.address.clone(), + idx: key.clone(), + val: val.clone(), + }], + }; + + MachineRecord { + stack: Some(stack_rec), + mem: None, + storage: Some(storage_change), + pc: (mach.pc(), mach.pc() + self.byte_size()), + constraints: None, + halt: false, + } + } + Instruction::Jump => { + let jump_dest = mach.stack().peek().unwrap(); + + let jump_dest_concrete = jump_dest.as_ref().simplify().as_u64().unwrap() as usize; + let stack_rec = StackChange { + pop_qty: 1, + push_qty: 0, + swap_depth: 0, + ops: vec![StackOp::Pop], + }; + MachineRecord { + stack: Some(stack_rec), + pc: (mach.pc(), jump_dest_concrete), + constraints: None, + mem: Default::default(), + halt: false, + storage: None, } } - Instruction::SLoad => todo!(), - Instruction::SStore => todo!(), - Instruction::Jump => todo!(), Instruction::JumpI => { let jump_dest = mach.stack().peek().unwrap(); let cond = mach.stack().peek_nth(1).unwrap(); @@ -832,6 +1046,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { let stack_rec = StackChange { pop_qty: 2, + swap_depth: 0, push_qty: 0, ops: vec![StackOp::Pop, StackOp::Pop], }; @@ -842,21 +1057,24 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { constraints: Some(cond), mem: Default::default(), halt: false, + storage: None, } } Instruction::Pc => { let pc = BitVec::new_literal(mach.pc() as u64); let stack_rec = StackChange { pop_qty: 0, + swap_depth: 0, push_qty: 1, ops: vec![StackOp::Push(pc)], }; MachineRecord { stack: Some(stack_rec), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), constraints: None, mem: Default::default(), halt: false, + storage: None, } } Instruction::MSize => { @@ -869,13 +1087,33 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack, mem: Default::default(), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), halt: false, + storage: None, constraints: None, } } - Instruction::Gas => todo!(), - Instruction::JumpDest => todo!(), + Instruction::Gas => { + let gas_arg: BitVec<256> = random_bv_arg(); + let gas = gas().apply(&[gas_arg.as_ref()]).as_bv().unwrap(); + MachineRecord { + stack: Some(StackChange::with_ops(vec![StackOp::Push(gas.into())])), + pc: (mach.pc(), mach.pc() + self.byte_size()), + mem: None, + halt: false, + storage: None, + constraints: None, + } + + }, + Instruction::JumpDest => MachineRecord { + stack: None, + pc: (mach.pc(), mach.pc() + self.byte_size()), + mem: Default::default(), + halt: false, + storage: None, + constraints: None, + }, Instruction::Push1(bv) => { let new_bv = bv.as_ref().zero_ext(31).into(); @@ -883,9 +1121,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -896,9 +1135,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -909,9 +1149,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -922,9 +1163,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -935,9 +1177,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -948,9 +1191,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -961,9 +1205,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -974,9 +1219,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -987,9 +1233,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1000,9 +1247,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1013,9 +1261,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1026,9 +1275,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1039,9 +1289,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1052,9 +1303,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1065,9 +1317,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1078,9 +1331,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1091,9 +1345,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1104,9 +1359,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1117,9 +1373,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1130,9 +1387,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1143,9 +1401,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1156,9 +1415,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1169,9 +1429,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1182,9 +1443,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1195,9 +1457,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1208,9 +1471,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1221,9 +1485,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1234,9 +1499,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1247,9 +1513,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1260,9 +1527,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1273,9 +1541,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1284,9 +1553,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1306,22 +1576,22 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::Dup14 => exec_dup_nth(mach, 14), Instruction::Dup15 => exec_dup_nth(mach, 15), Instruction::Dup16 => exec_dup_nth(mach, 16), - Instruction::Swap1 => todo!(), - Instruction::Swap2 => todo!(), - Instruction::Swap3 => todo!(), - Instruction::Swap4 => todo!(), - Instruction::Swap5 => todo!(), - Instruction::Swap6 => todo!(), - Instruction::Swap7 => todo!(), - Instruction::Swap8 => todo!(), - Instruction::Swap9 => todo!(), - Instruction::Swap10 => todo!(), - Instruction::Swap11 => todo!(), - Instruction::Swap12 => todo!(), - Instruction::Swap13 => todo!(), - Instruction::Swap14 => todo!(), - Instruction::Swap15 => todo!(), - Instruction::Swap16 => todo!(), + Instruction::Swap1 => exec_swap_nth(mach, 1), + Instruction::Swap2 => exec_swap_nth(mach, 2), + Instruction::Swap3 => exec_swap_nth(mach, 3), + Instruction::Swap4 => exec_swap_nth(mach, 4), + Instruction::Swap5 => exec_swap_nth(mach, 5), + Instruction::Swap6 => exec_swap_nth(mach, 6), + Instruction::Swap7 => exec_swap_nth(mach, 7), + Instruction::Swap8 => exec_swap_nth(mach, 8), + Instruction::Swap9 => exec_swap_nth(mach, 9), + Instruction::Swap10 => exec_swap_nth(mach, 10), + Instruction::Swap11 => exec_swap_nth(mach, 11), + Instruction::Swap12 => exec_swap_nth(mach, 12), + Instruction::Swap13 => exec_swap_nth(mach, 13), + Instruction::Swap14 => exec_swap_nth(mach, 14), + Instruction::Swap15 => exec_swap_nth(mach, 15), + Instruction::Swap16 => exec_swap_nth(mach, 16), Instruction::Log0 => todo!(), Instruction::Log1 => todo!(), Instruction::Log2 => todo!(), @@ -1330,26 +1600,43 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { Instruction::Create => todo!(), Instruction::Call => todo!(), Instruction::CallCode => todo!(), - Instruction::Return => todo!(), + Instruction::Return => MachineRecord { + mem: None, + stack: None, + storage: None, + pc: (mach.pc(), mach.pc()), + constraints: None, + halt: true, + }, Instruction::DelegateCall => todo!(), Instruction::Create2 => todo!(), Instruction::StaticCall => todo!(), - Instruction::Revert => todo!(), + Instruction::Revert => MachineRecord { + mem: None, + stack: None, + storage: None, + pc: (mach.pc(), mach.pc()), + constraints: None, + halt: true, + }, Instruction::Invalid => todo!(), Instruction::SelfDestruct => todo!(), + Instruction::SignExtend => todo!(), Instruction::Push(bv) => { let stack_change = StackChange { pop_qty: 0, push_qty: 1, + swap_depth: 0, ops: vec![StackOp::Push(bv.clone())], }; let pc = mach.pc(); MachineRecord { stack: Some(stack_change), mem: Default::default(), - pc: (pc, pc + 1), + pc: (pc, pc + self.byte_size()), constraints: None, halt: false, + storage: None, } } Instruction::IsZero => { @@ -1364,9 +1651,10 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { MachineRecord { stack: Some(StackChange::with_ops(ops)), - pc: (mach.pc(), mach.pc() + 1), + pc: (mach.pc(), mach.pc() + self.byte_size()), mem: Default::default(), halt: false, + storage: None, constraints: None, } } @@ -1374,7 +1662,7 @@ impl<'ctx> MachineInstruction<'ctx, 32> for Instruction { } } -pub fn pop() -> StackOp { +pub fn pop() -> StackOp { StackOp::Pop } pub fn add() -> Instruction { @@ -1433,6 +1721,12 @@ pub fn dup14() -> Instruction { pub fn dup15() -> Instruction { Instruction::Dup15 } +pub fn dup16() -> Instruction { + Instruction::Dup16 +} +// pub fn push(size: usize, val: BitVec<>) -> Instruction { +// Instruction::Push5(BitVec::default()) +// } pub fn push1(v: BitVec<1>) -> Instruction { Instruction::Push1(v) diff --git a/src/lib.rs b/src/lib.rs index 12b2183..37fbaf7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,21 @@ #![allow(unused)] // #![feature(adt_const_params)] extern crate z3 as z3_ext; +pub mod conversion; +pub mod exec; pub mod instruction; pub mod machine; pub mod memory; +pub mod parser; pub mod record; pub mod smt; pub mod stack; pub mod state; +pub mod storage; pub mod traits; use instruction::*; +use paste::{expr, item, paste}; +use rand::Rng; use smt::*; use stack::*; use z3_ext::{ @@ -17,9 +23,32 @@ use z3_ext::{ AstKind, Config, Context, Model, SatResult, Solver, }; -pub fn bvi(val: impl Into) -> BitVec { +pub fn bvi(val: impl Into) -> BitVec { BitVec::new_literal(val.into() as u64) } + +pub fn bvi_32byte(val: u64) -> BitVec<32> { + BitVec::new_literal(val) +} + +pub fn bvi_8byte(val: u64) -> BitVec<8> { + BitVec::new_literal(val) +} pub fn bvc(val: impl AsRef) -> BitVec<32> { BitVec::new_const(val) } +pub fn random_bv_arg() -> BitVec { + let mut rng = rand::thread_rng(); + let rand_num: u64 = rng.gen(); + BitVec::new_literal(rand_num) +} + +#[cfg(test)] +mod test { + /* + + + */ + pub const SIMPLE_COUNTER: &str = r"6080604052348015600f57600080fd5b5060043610603c5760003560e01c80633fb5c1cb1460415780638381f58a146053578063d09de08a14606d575b600080fd5b6051604c3660046083565b600055565b005b605b60005481565b60405190815260200160405180910390f35b6051600080549080607c83609b565b9190505550565b600060208284031215609457600080fd5b5035919050565b60006001820160ba57634e487b7160e01b600052601160045260246000fd5b506001019056fea2646970667358221220f0cfb2159c518c3da0ad864362bad5dc0715514a9ab679237253d506773a0a1b64736f6c63430008130033"; + pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; +} diff --git a/src/machine.rs b/src/machine.rs index 12c3d20..634958e 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -7,10 +7,13 @@ use z3_ext::{ AstKind, Config, Context, Model, SatResult, Solver, }; +use crate::exec::Execution; use crate::instruction::*; use crate::memory::*; +use crate::parser::Program; use crate::state::evm::EvmState; use crate::state::tree::{NodeId, StateTree}; +use crate::storage::{AccountStorage, Address}; use crate::traits::{Machine, MachineComponent, MachineInstruction, MachineState}; use crate::{ bvc, bvi, @@ -53,51 +56,53 @@ impl ExecutionSummary { } pub type ExecBranch<'ctx> = (EvmState, Vec>); + +pub struct TransactionContext { + calldata: Option>, + output: Option>, + storage: HashMap, +} + +// The Evm is an *implementation* of the Machine trait +// Its job is merely to orchestrate the incremental construction of an Execution +// by initializing an Execution with a starting StateTree and calling Execution.step() +// It also provides a handler to an Execution, which in turn provides a handler to EvmState +// so that when an Instruction requires *reading* environmental / network state OR when an Instruction's behavior +// *depends* on env / network state, it can access it through the Evm, which can be initialized with things like a Transaction context #[derive(Clone)] pub struct Evm<'ctx> { - pgm: Vec, + pgm: Program, pub states: StateTree<'ctx>, change_log: Vec>, pub inverse_state: HashMap, } impl<'ctx> Evm<'ctx> { - // Given a machine (which has its internal state tree) & a machine record - // this method returns a new state tree containing all possible new machine states - // that would result from taking the step represented by the machine record - // fn state_transition(tree: StateTree<'ctx>, rec: MachineRecord<32>) -> StateTree { - // let MachineRecord {pc, stack, mem, constraints, halt} = rec.clone(); - // let mut curr_node = tree.val.clone(); - // let mut new_state = tree.clone(); - // eprintln!("STACK BEFORE STATE TRANSITION: {:#?}", curr_node.stack()); - // - // let (straight_exec, jump_exec) = curr_node.state_transition(rec); - // let (left_mach, mut left_mach_new_conds) = straight_exec; - // eprintln!("STACK AFTER STATE TRANSITION: {:#?}", left_mach.stack()); - // if let Some(conds) = tree.path_condition { - // left_mach_new_conds.push(conds.clone()); - // let cond_slice = left_mach_new_conds.iter().map(|c| c).collect::>(); - // new_state.insert_left((left_mach,Bool::and(ctx(), &cond_slice.as_slice()))); - // } - // - // - // if let Some(jump_state) = jump_exec { - // new_state.insert_right((jump_state.0, constraints)); - // } - // new_state - // - // todo!() - // } + pub fn with_pgm(pgm: Program) -> Self { + let evm_state = EvmState::with_pgm(pgm.clone()); + Self { + pgm, + states: StateTree { + id: NodeId::new(), + val: evm_state, + path_condition: None, + left: None, + right: None, + }, + change_log: vec![], + inverse_state: Default::default(), + } + } + + pub fn set_init_state(&mut self, state: EvmState) { + self.states.val = state; + } } impl<'ctx> Evm<'ctx> { - pub fn new(pgm: Vec) -> Self { - let evm_state = EvmState { - memory: Default::default(), - stack: Default::default(), - pc: 0, - pgm: pgm.clone(), - }; + pub fn new(pgm: Program) -> Self { + let evm_state = EvmState::with_pgm(pgm.clone()); + Self { pgm, states: StateTree { @@ -112,102 +117,208 @@ impl<'ctx> Evm<'ctx> { } } - fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { - let evm_trace = self.exec(); + // A path from a node is the current node and the union of the paths of its children + pub fn paths(trace: Execution<'ctx>) -> Vec>)>> { + let mut paths_collected = vec![]; + + let mut curr_path = vec![]; + let tree = Some(Box::new(trace.states)); + StateTree::find_paths(&tree, &mut curr_path, &mut paths_collected); + paths_collected + } + + pub fn exec_check( + trace: Execution<'ctx>, + ) -> Vec<( + Vec<(NodeId, Instruction, Option>)>, + Option, + Option, + )> { let mut solver = z3_ext::Solver::new(ctx()); - evm_trace + let paths = Self::paths(trace); + let reachable = paths .into_iter() - .filter_map(|(state, constraints)| { - let constraint = constraints - .clone() - .into_iter() - .reduce(|c, e| Bool::and(ctx(), &[&c, &e])); - if let Some(constraint) = constraint { - solver.assert(&constraint); - } + .map(|path| { + let mut result = (path.clone(), None, None); + solver.push(); + path.iter().for_each(|step| { + if let Some(constraint) = step.2.clone() { + solver.assert(&constraint); + } + }); match solver.check() { SatResult::Sat => { let model = solver.get_model(); - eprintln!( - "State {:#?} is reachable.\nMODEL:{:#?}", - state, - solver.get_model() - ); - Some(((state, constraints), model)) + result.1 = Some(SatResult::Sat); + + result.2 = model.map(|m| m.to_string()); } SatResult::Unsat => { - eprintln!("Unsat"); - None + result.1 = Some(SatResult::Unsat); } SatResult::Unknown => { - eprintln!("Unknown"); - None + result.1 = Some(SatResult::Unknown); } } + solver.pop(1); + result }) - .collect::>() + .collect::>(); + reachable } + + // pub fn exec_check(&mut self) -> Vec<(ExecBranch, Option>)> { + // let evm_trace = self.exec(); + // let mut solver = z3_ext::Solver::new(ctx()); + // evm_trace + // .into_iter() + // .filter_map(|(state, constraints)| { + // let constraint = constraints + // .clone() + // .into_iter() + // .reduce(|c, e| Bool::and(ctx(), &[&c, &e])); + // if let Some(constraint) = constraint { + // solver.assert(&constraint); + // } + // match solver.check() { + // SatResult::Sat => { + // let model = solver.get_model(); + // eprintln!( + // "State {:#?} is reachable.\nMODEL:{:#?}", + // state, + // solver.get_model() + // ); + // Some(((state, constraints), model)) + // } + // SatResult::Unsat => { + // eprintln!("Unsat"); + // None + // } + // SatResult::Unknown => { + // eprintln!("Unknown"); + // None + // } + // } + // }) + // .collect::>() + // } } impl<'ctx> Machine<32> for Evm<'ctx> { type State = EvmState; - fn exec(&mut self) -> Vec> { - let mut curr_state = self.states.val.clone(); - let curr_id = self.states.id.clone(); - - let mut jump_ctx = vec![curr_id.id()]; - let mut state_tree = self.states.clone(); - let mut trace: Vec = vec![(curr_state, vec![])]; - let mut leaves: Vec = vec![]; - + fn exec(&mut self) -> Execution { + let mut halt = false; + let mut step_recs = vec![]; + let mut exec = Execution::new(self.states.val.clone(), self.pgm.clone()); + let first_step = exec.step_mut(); + step_recs.push(first_step); + let mut ids = vec![]; loop { - let curr_state = trace.pop(); - let mut temp_id_ptr = jump_ctx.pop(); - //eprintln!("Executing node with id {:?}", temp_id_ptr); - if let Some(curr_state) = curr_state { - let temp_id_ptr = temp_id_ptr.unwrap(); - - let (curr_state, curr_cond) = curr_state; - let mut curr_cond = curr_cond.clone(); - let mut branch_cond_pre = curr_cond.clone(); - let (next_state, next_state_branch) = curr_state.exec_once(); - if let Some(branch) = next_state_branch { - let (branch_state, branch_cond) = branch; - branch_cond_pre.extend(branch_cond); - let branch = (branch_state.clone(), branch_cond_pre.clone()); - - let branch_right_id = state_tree.insert_right_of(branch.clone(), temp_id_ptr); - - jump_ctx.push(branch_right_id); - if branch_state.can_continue() { - trace.push(branch); - } else { - leaves.push(branch); - } + if let Some(step) = step_recs.pop() { + eprintln!( + "HALTED LEFT: {}, HALTED RIGHT: {}", + step.halted_left(), + step.halted_right() + ); + eprintln!( + "LEFT ID: {:#?} RIGHT ID: {:#?}", + step.left_id(), + step.right_id() + ); + // if !step.halted_right() { + // let continue_from_right = step.right_id(); + if let Some(right_id) = step.right_id() { + ids.push(right_id.id()); + let nxt_right_step = exec.step_from_mut(right_id); + step_recs.push(nxt_right_step); } - let (nxt_state, nxt_constraints) = next_state; - curr_cond.extend(nxt_constraints); - let branch = (nxt_state.clone(), curr_cond.clone()); - // eprintln!("Inserting to the left of {:?}", temp_id_ptr); - - let branch_left_id = state_tree.insert_left_of(branch.clone(), temp_id_ptr); - // eprintln!("Inserted {} to the left of {}", branch_left_id, temp_id_ptr); - if nxt_state.can_continue() { - trace.push(branch); - jump_ctx.push(branch_left_id); - } else { - leaves.push(branch); + //} + // if !step.halted_left() { + // let continue_from_left = step.left_id(); + if let Some(left_id) = step.left_id() { + ids.push(left_id.id()); + let nxt_step = exec.step_from_mut(left_id); + step_recs.push(nxt_step); + } + // } + + if step.halted_left() && step.halted_right() { + eprintln!( + "Both have halted... Here are the step recs left: {:#?}", + step_recs + ); } } else { break; } } - self.states = state_tree; - leaves + eprintln!("All ids that were executed during a step: {:#?}", ids); + + exec } - fn pgm(&self) -> Vec { + // fn exec(&mut self) -> Vec> { + // let mut curr_state = self.states.val.clone(); + // let curr_id = self.states.id.clone(); + + // let mut jump_ctx = vec![curr_id.id()]; + // let mut state_tree = self.states.clone(); + // let mut trace: Vec = vec![(curr_state, vec![])]; + // let mut leaves: Vec = vec![]; + + // loop { + // let curr_state = trace.pop(); + // let mut temp_id_ptr = jump_ctx.pop(); + // //eprintln!("Executing node with id {:?}", temp_id_ptr); + // if let Some(curr_state) = curr_state { + // let temp_id_ptr = temp_id_ptr.unwrap(); + + // let (curr_state, curr_cond) = curr_state; + // let mut curr_cond = curr_cond.clone(); + // let mut branch_cond_pre = curr_cond.clone(); + // let (next_state, next_state_branch, halt) = curr_state.exec_once(); + // if let Some(branch) = next_state_branch { + // let (branch_state, branch_cond) = branch; + // branch_cond_pre.extend(branch_cond); + // let branch = (branch_state.clone(), branch_cond_pre.clone()); + + // let branch_right_id = state_tree.insert_right_of(branch.clone(), temp_id_ptr); + + // jump_ctx.push(branch_right_id); + // if branch_state.can_continue() { + // trace.push(branch); + // } else { + // leaves.push(branch); + // } + // } + + // let (nxt_state, nxt_constraints) = next_state; + // eprintln!("NEXT STATE {:#?}", nxt_state); + // curr_cond.extend(nxt_constraints); + // let branch = (nxt_state.clone(), curr_cond.clone()); + // // eprintln!("Inserting to the left of {:?}", temp_id_ptr); + + // let branch_left_id = state_tree.insert_left_of(branch.clone(), temp_id_ptr); + // // eprintln!("Inserted {} to the left of {}", branch_left_id, temp_id_ptr); + // if nxt_state.can_continue() && !halt { + // trace.push(branch); + // jump_ctx.push(branch_left_id); + // } else { + // leaves.push(branch); + // } + // if halt { + // break; + // } + // } else { + // break; + // } + // } + // self.states = state_tree; + // leaves + // } + + fn pgm(&self) -> Program { self.pgm.clone() } @@ -233,7 +344,7 @@ impl MachineState<32> for EvmState { type PC = usize; fn pc(&self) -> Self::PC { - self.pc + self.pgm_counter() } fn stack(&self) -> &Stack<32> { @@ -267,6 +378,22 @@ impl MachineState<32> for EvmState { fn mem_apply(&mut self, mem_rec: MemChange) { self.memory.apply_change(mem_rec); } + + fn storage(&self) -> &AccountStorage { + &self.storage + } + + fn storage_write(&mut self, idx: Index, val: crate::storage::StorageValue) { + self.storage.sstore(idx, val); + } + + fn storage_read(&self, idx: &Index) -> crate::storage::StorageValue { + self.storage.sload(idx) + } + + fn storage_apply(&mut self, storage_rec: StorageChange) { + self.storage.apply_change(storage_rec); + } } pub struct EvmExecutor<'ctx> { @@ -289,31 +416,27 @@ fn machine_returns_one_exec_for_non_branching_pgm() { add(), push32(bvi(7)), Instruction::JumpI, - Instruction::Push(bvi(100)), + Instruction::Push32(bvi(100)), push32(bvi(50)), ]; - let mut evm = Evm::new(pgm); - - { - let sat_branches = evm.exec_check(); - assert!( - sat_branches.first().is_some() - && sat_branches - .first() - .unwrap() - .0 - .0 - .stack() - .peek_nth(1) - .cloned() - .unwrap() - == bvi(100) - ); - - assert_eq!(sat_branches.len(), 1); - } - eprintln!("STATES > {:#?}", evm.states); + // let mut evm = Evm::new(pgm); + // let execution = evm.exec(); + // let exec_tree = &execution.states; + // let final_states = exec_tree.leaves(); + // assert_eq!(2, final_states.len()); + // assert_eq!( + // final_states + // .first() + // .unwrap() + // .val + // .stack() + // .peek_nth(1) + // .cloned() + // .unwrap(), + // bvi(100) + // ); + // eprintln!("Final states: {:#?}", final_states); } #[test] @@ -324,38 +447,28 @@ fn test_mem_store_mem_load() { Instruction::MStore, push32(bvi(2)), Instruction::MLoad, - push32(bvi(5)), - Instruction::MStore8, - push32(bvi(5)), - Instruction::MLoad, + // push32(bvi(5)), + // Instruction::MStore8, + // push32(bvi(5)), + // Instruction::MLoad, ]; - /** - stack memory - 3 null - 2 3 null - - null {2: 3} - 2 {2 : 3} - 3 {2 : 3} - 5 3 {2: 3} - null {2: 3, 5: 3} - 3 {2: 3, 5: 3} - */ - let mut evm = Evm::new(pgm); - - { - let sat_branches = evm.exec_check(); - assert_eq!(sat_branches.len(), 1); - let top = sat_branches - .first() - .unwrap() - .0 - .0 - .stack() - .peek() - .cloned() - .unwrap(); - assert_eq!(top, bvi(3)); - } - eprintln!("STATES > {:#?}", evm.states); + + // let mut evm = Evm::new(pgm); + + // { + // let sat_branches = evm.exec_check(); + // assert_eq!(sat_branches.len(), 1); + // let top = sat_branches + // .first() + // .unwrap() + // .0 + // .0 + // .stack() + // .peek() + // .cloned() + // .unwrap(); + // eprintln!("Stack top size: {:#?}", top.as_ref().get_size()); + // assert_eq!(top, bvi(3)); + // } + //eprintln!("STATES > {:#?}", evm.states); } diff --git a/src/memory.rs b/src/memory.rs index fe8d16b..bf965c3 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,4 +1,5 @@ use crate::bvi; +use ruint::aliases::U1; use std::collections::hash_map::Entry; use std::collections::HashMap; use z3_ext::ast::{Ast, BV}; @@ -21,6 +22,14 @@ impl MachineComponent for Memory { let mut highest_idx = self.highest_idx; ops_log.into_iter().for_each(|op| match op { MemOp::Write { val, idx } => { + let mut val = val; + val.simplify(); + let mut idx = idx; + idx.simplify(); + eprintln!( + "MEM WRITE FOR MEM APPLY: idx: {:#?}, value: {:#?}", + idx, val + ); let idx_cmp: usize = idx.clone().into(); if idx_cmp > highest_idx { highest_idx = idx_cmp; @@ -54,7 +63,7 @@ impl Memory { } pub fn write(&mut self, idx: Index, val: BitVec<1>) { - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx = idx.into(); self.inner.insert(idx, val); // Pad rest with zero for i in 0..30 { @@ -62,25 +71,46 @@ impl Memory { } } pub fn read(&self, idx: Index) -> BitVec<1> { - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx: usize = idx.into(); let val = self.inner.get(idx).unwrap().clone(); val } + + pub fn read_with_offset( + &self, + offset: Index, + size: impl Into + Clone, + ) -> Vec> { + let idx: usize = offset.into(); + + eprintln!("IDX: {idx:} and size: {:#?}", size.clone().into()); + let val = self.inner[idx..(idx + size.clone().into())].to_vec(); + eprintln!("VAL IN MEM READ EITH OFFSET: {:#?}", val); + val + } pub fn read_word(&self, idx: Index) -> BitVec<32> { let mut i = 0; - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx: usize = idx.into(); let mut bytes = vec![]; let mut mem = self.inner.clone(); + // eprintln!(" MEM IN READ WORD: {:#?}", mem); while i < 32 { let idx = idx + 31; + let val = mem.get(idx - i).unwrap().as_ref().clone(); + //eprintln!("MEM VAL IN READ WORD FOR IDX - i:\nmem loc {:#?}\nval: {:#?}", (idx - i), val); bytes.push(val); i += 1; } let mut new_bv: BitVec<1> = BitVec::default(); let mut new_bv_inner = new_bv.as_ref().clone(); - bytes.into_iter().for_each(|b| { - new_bv_inner = new_bv_inner.concat(&b); + bytes.into_iter().enumerate().for_each(|(i, b)| { + if i == 0 { + new_bv = BitVec::with_bv(b); + new_bv_inner = new_bv.as_ref().clone(); + } else { + new_bv_inner = new_bv_inner.concat(&b); + } }); BitVec { inner: BVType::Z3(new_bv_inner), @@ -89,7 +119,7 @@ impl Memory { } pub fn write_word(&mut self, idx: Index, word: BitVec<32>) { - let idx = idx.as_ref().as_u64().unwrap() as usize; + let idx = idx.into(); if idx > self.size() { for i in 0..idx - self.size() { self.inner.push(BitVec::default()); @@ -98,7 +128,7 @@ impl Memory { //eprintln!("WORD: {word:#?}"); for i in 0..32 { let ii = 32 - i - 1; - let bv = word.as_ref().extract(ii * 8 + 7, ii * 8); + let bv = word.as_ref().extract(ii * 8 + 7, ii * 8).simplify(); // eprintln!("Extracted: {:#?}", bv); let bv: BitVec<1> = bv.into(); @@ -107,3 +137,25 @@ impl Memory { } } } + +impl std::fmt::Display for Memory { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut mem_str = format!( + "Memory:\nSize: {} Highest Index: {}", + self.size(), + self.highest_idx + ); + self.inner.iter().enumerate().for_each(|(i, slot)| { + let str_to_push = if slot.as_ref().is_const() { + let slot_str = format!("{} --> {}\n", i, slot.as_ref()); + slot_str + } else { + let slot_val_as_bytes = slot.as_ref().as_u64().unwrap().to_be_bytes(); + let slot_str = format!("{} --> {:#?}\n", i, slot_val_as_bytes); + slot_str + }; + mem_str = format!("{}{}", mem_str, str_to_push); + }); + write!(f, "{}", mem_str) + } +} diff --git a/src/parser.rs b/src/parser.rs new file mode 100644 index 0000000..d8eadcf --- /dev/null +++ b/src/parser.rs @@ -0,0 +1,655 @@ +use std::collections::HashMap; + +use crate::{bvi, instruction::*, smt::BitVec}; +use hex::decode; +use revm::{opcode::OpCode, OPCODE_JUMPMAP}; +use ruint::Uint; +#[derive(Default)] +pub struct Parser<'a> { + pgm: &'a str, + parsed: Program, +} + +impl<'a> Parser<'a> { + pub fn with_pgm(pgm: &'a str) -> Self { + Self { + pgm, + ..Default::default() + } + } + + pub fn parse(&self) -> Program { + let bytes = decode(self.pgm).unwrap(); + let mut opcodes: Vec = vec![]; + + let mut pgm = vec![]; + let mut skip_size = 0; + let mut idx = 0_usize; + let mut pgm_map = HashMap::new(); + for b in &bytes { + let b = *b; + if skip_size > 0 { + skip_size -= 1; + continue; + idx += 1; + } + if is_push(b) { + // push1 0xab push4 0xabcd + let sz = push_size(b); + let (inst, push_size, new_bytes) = parse_push(&bytes[idx as usize..]); + skip_size = push_size; + pgm_map.insert(idx, inst.clone()); + idx += skip_size as usize; + pgm.push(inst); + } else if is_dup(b) { + let inst = parse_dup(b); + pgm_map.insert(idx, inst.clone()); + pgm.push(inst); + } else if is_swap(b) { + let inst = parse_swap(b); + pgm_map.insert(idx, inst.clone()); + pgm.push(inst); + } else { + let inst = Instruction::from(b); + pgm_map.insert(idx, inst.clone()); + pgm.push(inst); + } + idx += 1; + } + Program { + map: pgm_map, + pgm, + size: idx + 1, + } + } +} + +// Returns instruction + any left over bytes in the slice after extracting the opcode & opcode args +fn parse_push(bytes: &[u8]) -> (Instruction, u8, Vec) { + let instruction_byte = *bytes.first().unwrap(); + let push_size = push_size(instruction_byte); + //eprintln!("PUSH SIZE IS {}", push_size); + //eprintln!("Bytes len is {}", bytes.len()); + if bytes.len() - 1 < push_size as usize { + let pad_len = push_size as usize - bytes.len() + 1; + // eprintln!("pad len: {}", pad_len); + let mut new_bytes = bytes.to_vec(); + for _ in (0..pad_len) { + new_bytes.push(0); + } + let push_val = &new_bytes[1..(push_size + 1) as usize]; + ( + push_op(push_size, push_val), + push_size, + new_bytes[(push_size) as usize..new_bytes.len()].to_vec(), + ) + } else { + let push_val = &bytes[1..(push_size + 1) as usize]; + //eprintln!("PUSH VAL IS {:#?}", push_val); + ( + push_op(push_size, push_val), + push_size, + bytes[(push_size) as usize..bytes.len()].to_vec(), + ) + } +} + +fn parse_dup(byte: u8) -> Instruction { + dup_op(dup_size(byte)) +} + +fn parse_swap(byte: u8) -> Instruction { + swap_op(swap_size(byte)) +} + +fn is_dup(b: u8) -> bool { + 0x80 <= b && 0x8f >= b +} + +fn is_swap(b: u8) -> bool { + 0x90 <= b && 0x9f >= b +} + +fn is_push(b: u8) -> bool { + 0x60 <= b && 0x7f >= b +} + +fn dup_size(b: u8) -> u8 { + if b >= 0x80 { + b - 0x80 + 1 + } else { + 0 + } +} + +fn swap_size(b: u8) -> u8 { + if b >= 0x90 { + b - 0x90 + 1 + } else { + 0 + } +} +fn push_size(b: u8) -> u8 { + if b >= 0x60 { + b - 0x60 + 1 + } else { + 0 + } +} + +// Add zeroes to the left side of a byte array until the byte array is a certain +pub fn zero_extend(bytes: &[u8]) -> [u8; SZ] { + let mut extended_bytes: [u8; SZ] = [0u8; SZ]; + if bytes.len() < SZ { + let pad_size = SZ - bytes.len(); + let last_idx = SZ - 1; + let start_idx = last_idx - (bytes.len() - 1); + extended_bytes[start_idx..].clone_from_slice(&bytes); + let padding_len = SZ - bytes.len(); + for i in (0..pad_size - 1) { + extended_bytes[i] = 0; + } + } else { + extended_bytes.copy_from_slice(bytes); + } + extended_bytes +} + +fn push_op(sz: u8, val: &[u8]) -> Instruction { + // let val = if val.len() < 8 { + // let mut zero_len = if val.len() < 8 {8 - val.len()} else {0}; + // let mut buf = vec![]; + // for _ in (0..zero_len) { + // buf.push(0); + // } + // buf.extend_from_slice(val); + + // let mut sliced = [0u8; 8]; + // sliced.copy_from_slice(&buf); + // u64::from_be_bytes(sliced) + // } else { + // let mut buf = vec![]; + // buf.copy_from_slice() + // u64::from_be_bytes(val) + // }; + + match sz { + 1 => { + let val = zero_extend::<1>(val); + push1(val.into()) + } + 2 => { + let val = zero_extend::<2>(val).into(); + push2(val) + } + 3 => { + let val = zero_extend::<3>(val).into(); + push3(val) + } + 4 => { + let val = zero_extend::<4>(val).into(); + push4(val) + } + 5 => { + let val = zero_extend::<5>(val).into(); + push5(val) + } + 6 => { + let val = zero_extend::<6>(val).into(); + push6(val) + } + 7 => { + let val = zero_extend::<7>(val).into(); + push7(val) + } + 8 => { + let val = zero_extend::<8>(val).into(); + push8(val) + } + 9 => { + let val = zero_extend::<9>(val).into(); + push9(val) + } + 10 => { + let val = zero_extend::<10>(val).into(); + push10(val) + } + 11 => { + let val = zero_extend::<11>(val).into(); + push11(val) + } + 12 => { + let val = zero_extend::<12>(val).into(); + push12(val) + } + 13 => { + let val = zero_extend::<13>(val).into(); + push13(val) + } + 14 => { + let val = zero_extend::<14>(val).into(); + push14(val) + } + 15 => { + let val = zero_extend::<15>(val).into(); + push15(val) + } + 16 => { + let val = zero_extend::<16>(val).into(); + push16(val) + } + 17 => { + let val = zero_extend::<17>(val).into(); + push17(val) + } + 18 => { + let val = zero_extend::<18>(val).into(); + push18(val) + } + 19 => { + let val = zero_extend::<19>(val).into(); + push19(val) + } + 20 => { + let val = zero_extend::<20>(val).into(); + push20(val) + } + 21 => { + let val = zero_extend::<21>(val).into(); + push21(val) + } + 21 => { + let val = zero_extend::<22>(val).into(); + push22(val) + } + 23 => { + let val = zero_extend::<23>(val).into(); + push23(val) + } + 24 => { + let val = zero_extend::<24>(val).into(); + push24(val) + } + 25 => { + let val = zero_extend::<25>(val).into(); + push25(val) + } + 26 => { + let val = zero_extend::<26>(val).into(); + push26(val) + } + 27 => { + let val = zero_extend::<27>(val).into(); + push27(val) + } + 28 => { + let val = zero_extend::<28>(val).into(); + push28(val) + } + 29 => { + let val = zero_extend::<29>(val).into(); + push29(val) + } + 30 => { + let val = zero_extend::<30>(val).into(); + push30(val) + } + 31 => { + let val = zero_extend::<31>(val).into(); + push31(val) + } + 32 => { + let val = zero_extend::<32>(val).into(); + push32(val) + } + _ => { + todo!() + } + } +} + +fn swap_op(sz: u8) -> Instruction { + match sz { + 1 => Instruction::Swap1, + 2 => Instruction::Swap2, + 3 => Instruction::Swap3, + 4 => Instruction::Swap4, + 5 => Instruction::Swap5, + 6 => Instruction::Swap6, + 7 => Instruction::Swap7, + 8 => Instruction::Swap8, + 9 => Instruction::Swap9, + 10 => Instruction::Swap10, + 11 => Instruction::Swap11, + 12 => Instruction::Swap12, + 13 => Instruction::Swap13, + 14 => Instruction::Swap14, + 15 => Instruction::Swap15, + 16 => Instruction::Swap16, + _ => todo!(), + } +} + +fn dup_op(sz: u8) -> Instruction { + match sz { + 1 => dup1(), + 2 => dup2(), + 3 => dup3(), + 4 => dup4(), + 5 => dup5(), + 6 => dup6(), + 7 => dup7(), + 8 => dup8(), + 9 => dup9(), + 10 => dup10(), + 11 => dup11(), + 12 => dup12(), + 13 => dup13(), + 14 => dup14(), + 15 => dup15(), + 16 => dup16(), + _ => todo!(), + } +} + +impl Instruction { + pub fn from_byte(value: u8) -> Self { + value.into() + } + + // Has to handle when it's a push or dup, otherwise easy 1-1 conversion + pub fn from_slice(bytes: &[u8]) -> Instruction { + let instruction_byte = *bytes.first().unwrap(); + + if is_push(instruction_byte) { + let push_size = push_size(instruction_byte); + let push_val = &bytes[1..push_size as usize]; + push_op(push_size, push_val) + } else if is_dup(instruction_byte) { + let dup_size = dup_size(instruction_byte); + dup_op(dup_size) + } else if is_swap(instruction_byte) { + let swap_size = swap_size(instruction_byte); + swap_op(swap_size) + } else { + Instruction::from(instruction_byte) + } + } +} + +impl From for Instruction { + fn from(value: u8) -> Self { + match value { + 0x00 => Instruction::Stop, + 0x01 => Instruction::Add, + 0x02 => Instruction::Mul, + 0x03 => Instruction::Sub, + 0x04 => Instruction::Div, + 0x05 => Instruction::SDiv, + 0x06 => Instruction::Mod, + 0x07 => Instruction::SMod, + 0x08 => Instruction::AddMod, + 0x09 => Instruction::MulMod, + 0x0a => Instruction::Exp, + 0x0b => Instruction::SignExtend, + 0x10 => Instruction::Lt, + 0x11 => Instruction::Gt, + 0x12 => Instruction::Slt, + 0x13 => Instruction::Sgt, + 0x14 => Instruction::Eq, + 0x15 => Instruction::IsZero, + 0x16 => Instruction::And, + 0x17 => Instruction::Or, + 0x18 => Instruction::Xor, + 0x19 => Instruction::Not, + 0x1a => Instruction::Byte, + 0x1b => Instruction::Shl, + 0x1c => Instruction::Shr, + 0x20 => Instruction::Sha3, + 0x30 => Instruction::Address, + 0x31 => Instruction::Balance, + 0x32 => Instruction::Origin, + 0x33 => Instruction::Caller, + 0x34 => Instruction::CallValue, + 0x35 => Instruction::CallDataLoad, + 0x36 => Instruction::CallDataSize, + 0x37 => Instruction::CallDataCopy, + 0x38 => Instruction::CodeSize, + 0x39 => Instruction::CodeCopy, + 0x3a => Instruction::GasPrice, + 0x3b => Instruction::ExtCodeSize, + 0x3c => Instruction::ExtCodeCopy, + 0x3d => Instruction::ReturnDataSize, + 0x3e => Instruction::ReturnDataCopy, + 0x3f => Instruction::ExtCodeHash, + 0x40 => Instruction::BlockHash, + 0x41 => Instruction::Coinbase, + 0x42 => Instruction::Timestamp, + 0x43 => Instruction::Number, + 0x44 => Instruction::Difficulty, + 0x45 => Instruction::GasLimit, + 0x46 => Instruction::ChainId, + 0x47 => Instruction::SelfBalance, + 0x50 => Instruction::Pop, + 0x51 => Instruction::MLoad, + 0x52 => Instruction::MStore, + 0x53 => Instruction::MStore8, + 0x54 => Instruction::SLoad, + 0x55 => Instruction::SStore, + 0x56 => Instruction::Jump, + 0x57 => Instruction::JumpI, + 0x58 => Instruction::Pc, + 0x59 => Instruction::MSize, + 0x5a => Instruction::Gas, + 0x5b => Instruction::JumpDest, + 0x60 => Instruction::Push1(Default::default()), + 0x61 => Instruction::Push2(Default::default()), + 0x62 => Instruction::Push3(Default::default()), + 0x63 => Instruction::Push4(Default::default()), + 0x64 => Instruction::Push5(Default::default()), + 0x65 => Instruction::Push6(Default::default()), + 0x66 => Instruction::Push7(Default::default()), + 0x67 => Instruction::Push8(Default::default()), + 0x68 => Instruction::Push9(Default::default()), + 0x69 => Instruction::Push10(Default::default()), + 0x6a => Instruction::Push11(Default::default()), + 0x6b => Instruction::Push12(Default::default()), + 0x6c => Instruction::Push13(Default::default()), + 0x6d => Instruction::Push14(Default::default()), + 0x6e => Instruction::Push15(Default::default()), + 0x6f => Instruction::Push16(Default::default()), + 0x70 => Instruction::Push17(Default::default()), + 0x71 => Instruction::Push18(Default::default()), + 0x72 => Instruction::Push19(Default::default()), + 0x73 => Instruction::Push20(Default::default()), + 0x74 => Instruction::Push21(Default::default()), + 0x75 => Instruction::Push22(Default::default()), + 0x76 => Instruction::Push23(Default::default()), + 0x77 => Instruction::Push24(Default::default()), + 0x78 => Instruction::Push25(Default::default()), + 0x79 => Instruction::Push26(Default::default()), + 0x7a => Instruction::Push27(Default::default()), + 0x7b => Instruction::Push28(Default::default()), + 0x7c => Instruction::Push29(Default::default()), + 0x7d => Instruction::Push30(Default::default()), + 0x7e => Instruction::Push31(Default::default()), + 0x7f => Instruction::Push32(Default::default()), + 0x80 => Instruction::Dup1, + 0x81 => Instruction::Dup2, + 0x82 => Instruction::Dup3, + 0x83 => Instruction::Dup4, + 0x84 => Instruction::Dup5, + 0x85 => Instruction::Dup6, + 0x86 => Instruction::Dup7, + 0x87 => Instruction::Dup8, + 0x88 => Instruction::Dup9, + 0x89 => Instruction::Dup10, + 0x8a => Instruction::Dup11, + 0x8b => Instruction::Dup12, + 0x8c => Instruction::Dup13, + 0x8d => Instruction::Dup14, + 0x8e => Instruction::Dup15, + 0x8f => Instruction::Dup16, + 0x90 => Instruction::Swap1, + 0x91 => Instruction::Swap2, + 0x92 => Instruction::Swap3, + 0x93 => Instruction::Swap4, + 0x94 => Instruction::Swap5, + 0x95 => Instruction::Swap6, + 0x96 => Instruction::Swap7, + 0x97 => Instruction::Swap8, + 0x98 => Instruction::Swap9, + 0x99 => Instruction::Swap10, + 0x9a => Instruction::Swap11, + 0x9b => Instruction::Swap12, + 0x9c => Instruction::Swap13, + 0x9d => Instruction::Swap14, + 0x9e => Instruction::Swap15, + 0x9f => Instruction::Swap16, + 0xa0 => Instruction::Log0, + 0xa1 => Instruction::Log1, + 0xa2 => Instruction::Log2, + 0xa3 => Instruction::Log3, + 0xa4 => Instruction::Log4, + 0xf0 => Instruction::Create, + 0xf1 => Instruction::Call, + 0xf2 => Instruction::CallCode, + 0xf3 => Instruction::Return, + 0xf4 => Instruction::DelegateCall, + 0xf5 => Instruction::Create2, + 0xfa => Instruction::StaticCall, + 0xfd => Instruction::Revert, + 0xfe => Instruction::Invalid, + 0xff => Instruction::SelfDestruct, + _ => Instruction::Invalid, + } + } +} + +#[derive(Default, Debug, Clone)] +pub struct Program { + pub map: HashMap, + pgm: Vec, + pub size: usize, +} + +impl Program { + pub fn get(&self, pc: usize) -> Option { + self.map.get(&pc).cloned() + } + + pub fn get_size(&self) -> usize { + self.size + } +} + +#[test] +fn is_push_works() { + for b in (0x60_u8..0x7f) { + assert!(is_push(b)); + } + + for b in (0x00_u8..0x5f) { + assert!(!is_push(b)); + } + + for b in (0x80..0xff_u8) { + assert!(!is_push(b)); + } +} + +/** + * pragma solidity ^0.8.3; + +contract Counter { + uint public count; + + // Function to get the current count + function get() public view returns (uint) { + return count; + } + + // Function to increment count by 1 + function inc() public { + count += 1; + } + + // Function to decrement count by 1 + function dec() public { + count -= 1; + } +} + */ +#[test] +fn can_parse_simple_pgm() { + const COUNTER_SOL_CODE: &'static str = "604260005260206000610040F3"; + + let pgm = Parser::with_pgm(COUNTER_SOL_CODE).parse(); + let sixty_four: BitVec<32> = bvi(0x0040); + // eprintln!("SIXTY FOUR: {:#?}", sixty_four); + let expected = vec![ + Instruction::Push1(bvi(0x42)), + Instruction::Push1(bvi(0)), + Instruction::MStore, + Instruction::Push1(bvi(0x20)), + Instruction::Push1(bvi(0)), + push2(bvi(0x0040)), + Instruction::Return, + ]; + + assert_eq!(expected, pgm.pgm); +} + +#[test] +fn can_parse_larger_pgm_with_storage() { + let pgm_raw = crate::test::COUNTER_WITH_STORAGE_MAPPING; + let pgm = Parser::with_pgm(pgm_raw).parse(); + + let expected_first_30 = vec![ + push1(bvi(0x80)), + push1(bvi(0x40)), + Instruction::MStore, + Instruction::CallValue, + dup1(), + Instruction::IsZero, + push2(bvi(0x0010)), + jumpi(), + push1(bvi(0x00)), + dup1(), + Instruction::Revert, + Instruction::JumpDest, + Instruction::Pop, + push1(bvi(0x05)), + push1(bvi(0x00)), + dup1(), + push1(bvi(0x01)), + dup2(), + Instruction::MStore, + push1(bvi(0x20)), + Instruction::Add, + Instruction::Swap1, + dup2(), + Instruction::MStore, + push1(bvi(0x20)), + Instruction::Add, + push1(bvi(0x00)), + Instruction::Sha3, + dup2(), + Instruction::Swap1, + Instruction::SStore, + Instruction::Pop, + push2(bvi(0x0197)), + ]; + + let inst10 = pgm.pgm.get(7).unwrap().clone(); + let inst10map = pgm.get(11).unwrap(); + assert_eq!(inst10, inst10map); + let pgm_first_30 = (&pgm.pgm[..33]).to_vec(); + assert_eq!(expected_first_30, pgm_first_30); + let pgm_map = pgm.map.into_iter().collect::>(); + + eprintln!("PROGRAM MAP INDICES: {:#?}", pgm_map); + let pgm_enumd = pgm_first_30.into_iter().enumerate().collect::>(); + eprintln!("Enumerated pgm indices: {:#?}", pgm_enumd); + // assert_eq!(pgm_enumd, pgm_map); +} diff --git a/src/record.rs b/src/record.rs index d88b231..0b2ad94 100644 --- a/src/record.rs +++ b/src/record.rs @@ -1,19 +1,23 @@ use crate::smt::BitVec; +use crate::storage::Address; use ruint::aliases::*; use ruint::Uint; +use z3_ext::ast::Ast; use z3_ext::ast::Bool; #[derive(Clone, Debug)] -pub struct MachineRecord { +pub struct MachineRecord { pub mem: Option, pub stack: Option>, + pub storage: Option, pub pc: (usize, usize), pub constraints: Option>, pub halt: bool, } pub type Index = BitVec<32>; +pub type Value = BitVec<32>; impl From for usize { fn from(idx: Index) -> Self { @@ -31,23 +35,26 @@ pub enum MemOp { Read { idx: Index }, } #[derive(Clone, Debug)] -pub enum StackOp { +pub enum StackOp { Push(BitVec), Pop, + Swap(usize), } #[derive(Default, Clone, Debug)] -pub struct StackChange { +pub struct StackChange { pub pop_qty: u64, pub push_qty: u64, + pub swap_depth: usize, pub ops: Vec>, } -impl StackChange { +impl StackChange { pub fn push(val: BitVec) -> Self { Self { pop_qty: 0, push_qty: 1, + swap_depth: 0, ops: vec![StackOp::Push(val)], } } @@ -59,16 +66,36 @@ impl StackChange { ops.iter().for_each(|op| match op { StackOp::Push(_) => push_qty += 1, StackOp::Pop => pop_qty += 1, + _ => (), }); Self { push_qty, pop_qty, + swap_depth: 0, ops, } } } -pub fn push(val: BitVec) -> StackOp { +#[derive(Clone, Debug)] +pub enum StorageOp { + Read { + addr: Address, + idx: Index, + }, + Write { + addr: Address, + idx: Index, + val: Value, + }, +} + +#[derive(Clone, Debug)] +pub struct StorageChange { + pub log: Vec, +} + +pub fn push(val: BitVec) -> StackOp { StackOp::Push(val) } diff --git a/src/smt/bitvec/mod.rs b/src/smt/bitvec/mod.rs index ae2f4bf..be2b26d 100644 --- a/src/smt/bitvec/mod.rs +++ b/src/smt/bitvec/mod.rs @@ -1,22 +1,40 @@ pub mod z3; + pub use self::z3::*; use super::{ctx, SolverType}; +use std::hash::{Hash, Hasher}; use z3_ext::ast::{Ast, BV}; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum BVType { Z3(BV<'static>), } pub type SymByte = BitVec<8>; -#[derive(Debug, Clone)] -pub struct BitVec { +#[derive(Debug, Clone, Eq)] +pub struct BitVec { pub inner: BVType, pub(crate) typ: super::SolverType, } -impl BitVec { +// impl PartialEq for BitVec { +// fn eq(&self, other: &Self) -> bool { +// let BVType::Z3(a) = &self.inner; +// let BVType::Z3(b) = &other.inner; +// +// a == b +// } +// } + +impl Hash for BitVec { + fn hash(&self, state: &mut H) { + self.as_ref().hash(state); + state.finish(); + } +} + +impl BitVec { pub fn with_bv(bv: BV<'static>) -> Self { Self { inner: BVType::Z3(bv), @@ -28,38 +46,42 @@ impl BitVec { self.inner = BVType::Z3(bv.simplify()); } } -impl Default for BitVec { +impl Default for BitVec { fn default() -> Self { let ctx = ctx(); Self { - inner: BVType::Z3(BV::from_u64(ctx, 0, SZ * 8)), + inner: BVType::Z3(BV::from_u64(ctx, 0, (SZ * 8) as u32)), typ: SolverType::Z3, } } } -impl PartialEq for BitVec { +impl PartialEq for BitVec { fn eq(&self, other: &Self) -> bool { - match &self.inner { - BVType::Z3(bv) => { - //eprintln!("LHS BV EQ: {:#?}", bv); - match &other.inner { - BVType::Z3(bvo) => { - //eprintln!("RHS BV EQ: {:#?}", bvo); - if let Some(bv1) = bv.as_u64() { - if let Some(bv2) = bvo.as_u64() { - bv1 == bv2 - } else { - false - } - } else { - false - } - } - _ => false, - } - } - _ => false, - } + let a = self.as_ref(); + let b = other.as_ref(); + + a.eq(b) + // match &self.inner { + // BVType::Z3(bv) => { + // //eprintln!("LHS BV EQ: {:#?}", bv); + // match &other.inner { + // BVType::Z3(bvo) => { + // //eprintln!("RHS BV EQ: {:#?}", bvo); + // if let Some(bv1) = bv.as_u64() { + // if let Some(bv2) = bvo.as_u64() { + // bv1 == bv2 + // } else { + // false + // } + // } else { + // false + // } + // } + // _ => false, + // } + // } + // _ => false, + // } } } diff --git a/src/smt/bitvec/z3.rs b/src/smt/bitvec/z3.rs index e8b052b..92a8925 100644 --- a/src/smt/bitvec/z3.rs +++ b/src/smt/bitvec/z3.rs @@ -3,12 +3,13 @@ use std::cmp::Ordering; use super::super::ctx; use super::{BVType, BitVec}; +use ruint::Uint; use z3::ast::{Ast, BV}; -impl BitVec { +impl BitVec { pub fn new_literal(val: u64) -> Self { let ctx = ctx(); - let bv = BV::from_u64(ctx, val, 256); + let bv = BV::from_u64(ctx, val, (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), @@ -16,58 +17,18 @@ impl BitVec { } pub fn new_const(name: impl AsRef) -> Self { - let bv = BV::new_const(ctx(), name.as_ref(), SZ * 8); + let bv = BV::new_const(ctx(), name.as_ref(), (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), } } } -impl From> for BitVec { - fn from(bv: BV<'static>) -> Self { - let bit_sz = SZ * 8; - let bvsz = bv.get_size(); - let bv = match bvsz.cmp(&bit_sz) { - Ordering::Less => bv.zero_ext(bit_sz - bvsz), - Ordering::Equal => bv, - Ordering::Greater => bv.extract(bit_sz, 0), - }; - // let bv = if bvsz < bit_sz { - // bv.zero_ext(bit_sz - bvsz) - // } else if bvsz > bit_sz { - // bv.extract(bit_sz, 0) - // } else { - // bv - // }; - Self { - inner: BVType::Z3(bv), - typ: Default::default(), - } - } -} - -impl From> for BV<'static> { - fn from(bv: BitVec) -> Self { - match bv.inner { - BVType::Z3(bv) => bv, - _ => panic!("Should never happen"), - } - } -} - -impl AsRef> for BitVec { - fn as_ref(&self) -> &BV<'static> { - match &self.inner { - BVType::Z3(bv) => bv, - _ => panic!("Should never happen"), - } - } -} -impl SymbolicValue, u64> for BitVec { +impl SymbolicValue, u64> for BitVec { fn new_literal(val: u64) -> Self { let ctx = ctx(); - let bv = BV::from_u64(ctx, val, 256); + let bv = BV::from_u64(ctx, val, (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), @@ -75,7 +36,7 @@ impl SymbolicValue, u64> for BitVec { } fn new_const(name: impl AsRef) -> Self { - let bv = BV::new_const(ctx(), name.as_ref(), SZ * 8); + let bv = BV::new_const(ctx(), name.as_ref(), (SZ * 8) as u32); Self { inner: BVType::Z3(bv), typ: Default::default(), diff --git a/src/stack.rs b/src/stack.rs index ef4b961..6e385d3 100644 --- a/src/stack.rs +++ b/src/stack.rs @@ -1,4 +1,4 @@ -use crate::record::StackChange; +use crate::{bvi, record::StackChange}; use std::fmt::{Debug, Formatter}; use super::smt::*; @@ -9,24 +9,25 @@ use z3_ext::{ Config, }; #[derive(Default, Debug, Clone)] -pub struct Stack { +pub struct Stack { stack: SmallVec<[BitVec; 1024]>, size: usize, } -impl Stack { +impl Stack { pub fn push(&mut self, val: BitVec) { self.size += 1; self.stack.push(val); } pub fn pop(&mut self) -> BitVec { + eprintln!("STACK SIZE: {} AND STACK TOP {:#?}", self.size, self.peek()); self.size -= 1; self.stack.pop().unwrap() } pub fn peek(&self) -> Option<&BitVec> { - self.stack.last() + self.stack.get(self.size - 1) } pub fn size(&self) -> usize { @@ -34,6 +35,7 @@ impl Stack { self.stack.len() } + // where n = 0 is top of the stack pub fn peek_nth(&self, n: usize) -> Option<&BitVec> { if n >= self.size() { return None; @@ -41,6 +43,44 @@ impl Stack { self.stack.get(self.size - n - 1) } + // where n is stack modulo top element; + pub(crate) fn swap_nth(&mut self, swap_depth: usize) { + eprintln!("SWAP EXECUTING AT DEPTH: {}", swap_depth); + if swap_depth < self.size() { + let mut new_stack = self.stack.clone(); + let top_idx = self.size - 1; + let swap_idx = self.size - swap_depth - 1; + let top = self.peek().cloned().unwrap(); + let swapped = self.peek_nth(swap_depth).cloned().expect(&format!( + "stack too deep to swap with depth {}. Stack size: {}", + swap_depth, + self.size() + )); + eprintln!("STACK BEFORE SWAP: {:#?}", new_stack); + new_stack = new_stack + .into_iter() + .enumerate() + .map(move |(idx, val)| { + if idx == swap_idx { + return top.clone(); + } else if idx == top_idx { + return swapped.clone(); + } else { + val + } + }) + .collect::>(); + eprintln!("STACK AFTER SWAP: {:#?}", new_stack); + // new_stack.remove(swap_idx); + // new_stack.insert(swap_idx, top); + // new_stack.pop(); + // new_stack.push(swapped); + self.stack = new_stack; + } else { + eprintln!("WILL NOT SWAP"); + } + } + pub fn peek_top(&self) -> Option<[&BitVec; N]> { if self.size() < N { return None; @@ -50,7 +90,7 @@ impl Stack { } } -impl MachineComponent for Stack { +impl MachineComponent for Stack { type Record = StackChange; fn apply_change(&mut self, rec: Self::Record) { @@ -58,6 +98,7 @@ impl MachineComponent for Stack { pop_qty, push_qty, ops, + swap_depth, } = rec; let mut new_stack = self.clone(); @@ -67,9 +108,31 @@ impl MachineComponent for Stack { crate::record::StackOp::Pop => { new_stack.pop(); } + crate::record::StackOp::Swap(depth) => {} }); + if swap_depth > 0 { + eprintln!( + "SWAP OCCURRING of DEPTH {}. STACK BEFORE: {:#?}", + swap_depth, new_stack + ); + new_stack.swap_nth(swap_depth as usize); + eprintln!("STACK AFTER {:#?}", new_stack); + } + self.stack = new_stack.stack; self.size = new_stack.size; } } + +#[test] +fn test_swap() { + let mut stack: Stack<1> = Stack::default(); + stack.push(bvi(1)); + stack.push(bvi(2)); + stack.push(bvi(3)); + stack.push(bvi(4)); + stack.swap_nth(2); + assert_eq!(stack.peek().cloned().unwrap(), bvi(2)); + assert_eq!(stack.peek_nth(2).cloned().unwrap(), bvi(4)); +} diff --git a/src/state/context.rs b/src/state/context.rs new file mode 100644 index 0000000..82992c2 --- /dev/null +++ b/src/state/context.rs @@ -0,0 +1,5 @@ +pub struct ExecutionContext { + block: BlockContext, +} + +pub struct BlockContext {} diff --git a/src/state/env.rs b/src/state/env.rs index 17f844c..21bad1f 100644 --- a/src/state/env.rs +++ b/src/state/env.rs @@ -1,10 +1,49 @@ -use z3_ext::ast::{Ast, AstKind}; +use std::collections::HashMap; + +use z3_ext::ast::{Array, Ast, AstKind, BV}; use z3_ext::FuncDecl; use z3_ext::Sort; -use crate::smt::ctx; - +use crate::parser::Program; +use crate::random_bv_arg; +use crate::smt::{ctx, BitVec}; +use crate::storage::Address; + +#[derive(Debug, Clone)] +pub struct ExecutionEnv { + code: HashMap>, + block: Block, + tx: TransactionContext, + result: Option +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum EvmResult { + Failed { + msg: String + }, + Success { + ret_val: BitVec<32> + } +} +#[derive(Debug, Clone)] +pub struct TransactionContext { + calldata: Option>>, + caller: Option
, + callvalue: Option>, +} + +#[derive(Debug, Clone)] +pub struct Block { + base_fee: Option>, + chain_id: Option>, + coinbase: Option
, + difficulty: Option>, + gaslimit: Option>, + number: Option>, + timestamp: Option> +} /** Note: Some of these functions in EVM have no arguments. The reason they are passed an argument here is because a zero argument function is @@ -28,6 +67,19 @@ pub fn call_data_load<'ctx>() -> FuncDecl<'ctx> { ) } +pub fn sha3<'ctx>(size: u32) -> FuncDecl<'ctx> { + let id = uuid::Uuid::new_v4(); + let func = FuncDecl::new( + ctx(), + format!("sha3_{}", id).as_str(), + &[&Sort::bitvector(ctx(), size)], + &Sort::bitvector(ctx(), 256), + ); + + eprintln!("SHA3 FUNC: {:#?}", func); + func +} + pub fn call_value<'ctx>() -> FuncDecl<'ctx> { let ctx = ctx(); FuncDecl::new(ctx, "callvalue", &[], &Sort::bitvector(ctx, 256)) @@ -48,9 +100,8 @@ pub fn origin<'ctx>() -> FuncDecl<'ctx> { FuncDecl::new(ctx, "origin", &[], &Sort::bitvector(ctx, 256)) } -pub fn address<'ctx>() -> FuncDecl<'ctx> { - let ctx = ctx(); - FuncDecl::new(ctx, "address", &[], &Sort::bitvector(ctx, 256)) +pub fn address() -> BitVec<20> { + random_bv_arg() } // Takes random bitvec as argument so that gas is not treated as a constant function. diff --git a/src/state/evm.rs b/src/state/evm.rs index 517d8c3..5f74ffd 100644 --- a/src/state/evm.rs +++ b/src/state/evm.rs @@ -1,5 +1,7 @@ use crate::machine::ExecBranch; +use crate::parser::Program; use crate::state::tree::NodeId; +use crate::storage::{AccountStorage, Address}; use crate::traits::MachineState; use crate::{ instruction::Instruction, @@ -10,14 +12,18 @@ use crate::{ }; use z3_ext::ast::Bool; -#[derive(Clone, Debug, Default)] +#[derive(Clone, Default)] pub struct EvmState { pub memory: Memory, + pub storage: AccountStorage, pub stack: Stack<32>, - pub pc: usize, - pub pgm: Vec, + pc: usize, + pub pgm: Program, + pub address: Address, + pub halt: bool, } + impl MachineComponent for EvmState { type Record = MachineRecord<32>; @@ -28,6 +34,7 @@ impl MachineComponent for EvmState { stack, mem, constraints, + storage, } = rec; if let Some(mem) = mem { self.memory.apply_change(mem); @@ -35,59 +42,77 @@ impl MachineComponent for EvmState { if let Some(stack) = stack { self.stack.apply_change(stack); } - - self.pc = pc.1; + self.halt = halt; + self.set_pc(pc.1); } } impl<'ctx> EvmState { - pub fn can_continue(&self) -> bool { - self.pc < self.pgm.len() - } - pub fn curr_instruction(&self) -> Instruction { - self.pgm.get(self.pc).cloned().unwrap() + pub fn with_pgm(pgm: Program) -> Self { + Self { + pgm, + ..Default::default() + } } - pub fn exec_once(mut self) -> (ExecBranch<'ctx>, Option>) { - let inst = self.curr_instruction(); - let change = inst.exec(&self); - - self.state_transition(change) + pub fn pgm_counter(&self) -> usize { + self.pc } - // Generates a set of next possible EvmStates given the state change record - pub fn state_transition( - &self, - rec: MachineRecord<32>, - ) -> (ExecBranch<'ctx>, Option>) { - let MachineRecord { - halt, - pc, - stack, - mem, - constraints, - } = rec; - let mut new_state = self.clone(); - if let Some(stack_rec) = stack { - new_state.stack_apply(stack_rec); + pub fn set_pc(&mut self, new_pc: usize) { + self.pc = new_pc; + if self.pc >= self.pgm.get_size() { + eprintln!( + "SET PC--- PC: {} -- PGM SIZE: {}", + self.pc, + self.pgm.get_size() + ); + self.halt = true; } + } - if let Some(mem_rec) = mem { - new_state.mem_apply(mem_rec); + pub fn inc_pc(&mut self) { + let curr_inst = self.curr_instruction(); + + self.set_pc(self.pc + curr_inst.byte_size()); + } + pub fn can_continue(&self) -> bool { + self.pc < self.pgm.get_size() && !self.halt + } + pub fn curr_instruction(&self) -> Instruction { + self.pgm + .get(self.pc) + .expect(&format!("Expected instruction at pc: {}", self.pc)) + } + pub fn curr_inst_debug(&self) -> Instruction { + if !self.can_continue() { + eprintln!("Curr instruction debug requested but cannot continue"); } + self.pgm.get(self.pc).unwrap() + } +} - if let Some(constraint) = constraints { - let mut does_jump_state = new_state.clone(); - does_jump_state.pc = pc.1; - new_state.pc += 1; - ( - (new_state, vec![constraint.not()]), - Some((does_jump_state, vec![constraint])), - ) - } else { - assert_eq!(pc.1, (pc.0 + 1)); - new_state.pc = pc.1; +impl std::fmt::Display for EvmState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + //write!(f, "Pc: {}\nHalted: {}\nStack: {:?}\n{}", self.pc(), self.halt, self.stack(), self.mem()) + write!( + f, + "Pc: {}, Stack: {:#?} halt: {:#?}", + self.pc(), + self.stack(), + self.halt + ) + } +} - ((new_state, vec![]), None) - } +impl std::fmt::Debug for EvmState { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("EvmState") + .field("stack", &self.stack) + .field("pc", &self.pc) + .field("address", &self.address) + .field("halt", &self.halt) + .field("instruction", &self.curr_inst_debug()) + .field("pgm size", &self.pgm.size) + .finish() } } diff --git a/src/state/mod.rs b/src/state/mod.rs index b6cf3f9..16c87ca 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -1,3 +1,4 @@ +pub mod context; pub mod env; pub mod evm; pub mod tree; diff --git a/src/state/tree.rs b/src/state/tree.rs index e94b8e3..34e828a 100644 --- a/src/state/tree.rs +++ b/src/state/tree.rs @@ -1,5 +1,5 @@ use super::evm::*; -use crate::{ctx, z3_ext::ast::Ast, z3_ext::ast::Bool}; +use crate::{ctx, instruction::Instruction, z3_ext::ast::Ast, z3_ext::ast::Bool}; use std::borrow::BorrowMut; use uuid::Uuid; @@ -43,8 +43,8 @@ impl NodeId { #[derive(Clone, Debug, Default)] pub struct StateTree<'ctx> { - pub(crate) id: NodeId, - pub(crate) val: EvmState, + pub id: NodeId, + pub val: EvmState, pub(crate) path_condition: Option>, pub(crate) left: Option>>, pub(crate) right: Option>>, @@ -117,6 +117,42 @@ impl<'ctx> StateTree<'ctx> { items } + pub fn find_paths( + node: &Option>>, + current_path: &mut Vec<(NodeId, Instruction, Option>)>, + all_paths: &mut Vec>)>>, + ) { + if let Some(ref node) = *node { + current_path.push(( + node.id.clone(), + node.val.curr_instruction(), + node.path_condition.clone(), + )); + + if node.left.is_none() && node.right.is_none() { + all_paths.push(current_path.clone()); + } else { + Self::find_paths(&node.left, current_path, all_paths); + Self::find_paths(&node.right, current_path, all_paths); + } + + current_path.pop(); + } + } + pub fn inorder_stateless(&self) -> Vec<(NodeId, Option>)> { + let mut items = vec![(self.id.clone(), self.path_condition.clone())]; + + if let Some(left) = &self.left { + let left_tree_inorder = left.inorder_stateless(); + items.extend(left_tree_inorder); + } + if let Some(right) = &self.right { + let right_tree_inorder = right.inorder_stateless(); + items.extend(right_tree_inorder); + } + items + } + pub fn insert(&mut self, tree: impl Into>) { if let Some(left) = &mut self.left { left.insert(tree); @@ -129,17 +165,36 @@ impl<'ctx> StateTree<'ctx> { } } + pub fn find_by_id(&self, id: &NodeId) -> Option<&StateTree<'ctx>> { + if self.id == *id { + Some(self) + } else { + if let Some(left) = self.left.as_ref() { + if let Some(found_l) = left.find_by_id(id) { + return Some(found_l); + } + } + if let Some(right) = self.right.as_ref() { + if let Some(found_r) = right.find_by_id(id) { + return Some(found_r); + } + } + None + } + } + pub fn insert_left_helper( &mut self, tree: impl Into>, id: Uuid, - ) -> Option { + ) -> Option<&StateTree> { let tree = tree.into(); let inserted_id = tree.id.id; if self.id.id == id { - self.left = Some(Box::new(tree)); - Some(inserted_id) + let tree = Box::new(tree); + self.left = Some(tree); + self.left.as_ref().map(|t| t.as_ref()) } else { let left_result = if let Some(left) = &mut self.left { left.insert_left_helper(tree.clone(), id) @@ -163,13 +218,13 @@ impl<'ctx> StateTree<'ctx> { &mut self, tree: impl Into>, id: Uuid, - ) -> Option { + ) -> Option<&StateTree> { let tree = tree.into(); let inserted_id = tree.id.id; if self.id.id == id { self.right = Some(Box::new(tree)); - Some(inserted_id) + self.right.as_ref().map(|t| t.as_ref()) } else { let left_result = if let Some(left) = &mut self.left { left.insert_right_helper(tree.clone(), id) @@ -188,9 +243,9 @@ impl<'ctx> StateTree<'ctx> { } } } - pub fn insert_left_of(&mut self, tree: impl Into>, id: Uuid) -> Uuid { + pub fn insert_left_of(&mut self, tree: impl Into>, id: Uuid) -> NodeId { match self.insert_left_helper(tree, id) { - Some(i) => i, + Some(i) => i.id.clone(), None => panic!("Could not find id {id} in the state tree"), } // if self.id.id == id { @@ -207,9 +262,9 @@ impl<'ctx> StateTree<'ctx> { // eprintln!("ALL NODES: {:?}", self.inorder()); } - pub fn insert_right_of(&mut self, tree: impl Into>, id: Uuid) -> Uuid { + pub fn insert_right_of(&mut self, tree: impl Into>, id: Uuid) -> NodeId { match self.insert_right_helper(tree, id) { - Some(i) => i, + Some(i) => i.id.clone(), None => panic!("Could not find id {id} in the state tree"), } } @@ -221,21 +276,31 @@ impl<'ctx> StateTree<'ctx> { leaves.push((self.val.clone(), self.path_condition.clone()).into()); return leaves; } - if let Some(left) = &self.left { - if left.left.is_none() && left.right.is_none() { - leaves.push((left.val.clone(), left.path_condition.clone()).into()); - } else { - leaves.extend(left.leaves()); - } + + if let Some(left) = self.left.as_ref() { + leaves.extend(left.leaves()); } - if let Some(right) = &self.right { - if right.right.is_none() && right.left.is_none() { - leaves.push((right.val.clone(), right.path_condition.clone()).into()); - } else { - leaves.extend(right.leaves()); - } + if let Some(right) = self.right.as_ref() { + leaves.extend(right.leaves()) } + + // if let Some(left) = &self.left { + + // if left.left.is_none() && left.right.is_none() { + // leaves.push((left.val.clone(), left.path_condition.clone()).into()); + // } else { + // leaves.extend(left.leaves()); + // } + // } + + // if let Some(right) = &self.right { + // if right.right.is_none() && right.left.is_none() { + // leaves.push((right.val.clone(), right.path_condition.clone()).into()); + // } else { + // leaves.extend(right.leaves()); + // } + // } leaves } diff --git a/src/storage.rs b/src/storage.rs new file mode 100644 index 0000000..4dfe61d --- /dev/null +++ b/src/storage.rs @@ -0,0 +1,188 @@ +use crate::{ + instruction::Instruction, + record::{StorageChange, StorageOp}, + traits::MachineComponent, +}; +use std::collections::HashMap; +use z3_ext::ast::{Array, Ast, BV}; + +use crate::smt::{ctx, BitVec}; +use crate::{bvc, bvi}; + +fn make_storage_arr() {} +#[derive(Debug, Clone, Default)] +pub struct AccountStorage { + inner: HashMap, StorageValue>, + touched: HashMap, bool>, + code: Option>, +} +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum StorageValue { + Array(Array<'static>), + BV(BitVec<32>), +} + +impl Default for StorageValue { + fn default() -> Self { + Self::BV(Default::default()) + } +} + +impl AccountStorage { + pub fn sstore(&mut self, index: BitVec<32>, val: StorageValue) { + self.inner.insert(index, val); + } + + pub fn sload(&self, index: &BitVec<32>) -> StorageValue { + if let Some(val) = self.inner.get(index) { + val.clone() + } else { + Default::default() + } + } +} + +pub type Address = BitVec<20>; + +#[derive(Debug, Clone, Default)] +pub struct GlobalStorage { + inner: HashMap, +} + +impl GlobalStorage { + pub fn init_with_addrs(addrs: Vec
) -> Self { + let mut store = Self::default(); + addrs.into_iter().for_each(|addr| { + store.inner.insert(addr, Default::default()); + }); + store + } + + pub fn get(&self, addr: &Address) -> AccountStorage { + self.inner.get(addr).cloned().unwrap_or_default() + } + pub fn new() -> Self { + Default::default() + } + pub fn with_address(mut self, addr: Address) -> Self { + self.inner.insert(addr, Default::default()); + self + } + pub fn with_contract(mut self, addr: Address, pgm: Vec) -> Self { + let mut account = AccountStorage::default(); + account.code = Some(pgm); + self.inner.insert(addr, account); + self + } +} + +impl MachineComponent for GlobalStorage { + type Record = StorageChange; + fn apply_change(&mut self, rec: Self::Record) { + let StorageChange { log } = rec; + let mut addr_record_map = HashMap::new(); + log.iter().for_each(|op| match op { + crate::record::StorageOp::Read { idx, addr } => { + addr_record_map + .entry(addr) + .and_modify(|logs: &mut Vec| { + logs.push(StorageOp::Read { + idx: idx.clone(), + addr: addr.clone(), + }) + }) + .or_insert(vec![StorageOp::Read { + idx: idx.clone(), + addr: addr.clone(), + }]); + } + crate::record::StorageOp::Write { addr, idx, val } => { + addr_record_map + .entry(addr) + .and_modify(|logs: &mut Vec| { + logs.push(StorageOp::Write { + idx: idx.clone(), + addr: addr.clone(), + val: val.clone(), + }) + }) + .or_insert(vec![StorageOp::Write { + idx: idx.clone(), + addr: addr.clone(), + val: val.clone(), + }]); + } + }); + addr_record_map + .into_iter() + .for_each(|(address, storage_ops_log)| { + let change = StorageChange { + log: storage_ops_log, + }; + self.inner + .entry(address.clone()) + .and_modify(|account| account.apply_change(change.clone())) + .or_insert_with(|| { + let mut new_acc = AccountStorage::default(); + new_acc.apply_change(change); + new_acc + }); + }) + } +} + +impl MachineComponent for AccountStorage { + type Record = StorageChange; + fn apply_change(&mut self, rec: Self::Record) { + let StorageChange { log } = rec; + log.into_iter().for_each(|op| match op { + crate::record::StorageOp::Read { idx, addr } => { + self.touched.insert(idx, true); + } + crate::record::StorageOp::Write { addr, idx, val } => { + self.touched.insert(idx.clone(), true); + self.inner.insert(idx, StorageValue::BV(val)); + } + }) + } +} + +#[test] +fn test_basic_lookup_works_in_acc_storage() { + let addr = Address::new_const("Address1"); + let mut acc_store = AccountStorage::default(); + acc_store.sstore(bvi(5), StorageValue::BV(bvc("val_at_idx_5"))); + + assert_eq!( + acc_store.sload(&bvi(5)), + StorageValue::BV(bvc("val_at_idx_5")) + ); +} + +#[test] +fn test_basic_lookup_global_storage() { + let addr = Address::new_const("Address1"); + let addr2 = Address::new_const("Address2"); + let mut global = GlobalStorage::init_with_addrs(vec![addr, addr2.clone()]); + + let mut addr_2_storage = global.get(&addr2); + addr_2_storage.sstore(bvi(3), StorageValue::BV(bvc("storage_val_at_idx_3"))); + global.inner.insert(addr2.clone(), addr_2_storage); + + assert_eq!( + global.get(&addr2).sload(&bvi(3)), + StorageValue::BV(bvc("storage_val_at_idx_3")) + ); +} + +#[test] +fn test_storage_with_solidity_mapping() {} + +// Storage keys must be concrete +// However, values can be symbolic +// In the case of compound structures like mappings, the following +// Global Storage: +// HashMap(Address -> AccountStorage) +// AccountStorage(BitVec<32> -> StorageValue) +// StorageValue(ConcreteBytes<32> OR SymbolicBytes<32>) +// diff --git a/src/traits.rs b/src/traits.rs index c6626d0..8f93468 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,13 +1,16 @@ +use crate::exec::Execution; use crate::instruction::Instruction; use crate::machine::{ExecBranch, ExecutionSummary}; use crate::memory::Memory; -use crate::record::{Index, MachineRecord, MemChange, StackChange}; +use crate::parser::Program; +use crate::record::{Index, MachineRecord, MemChange, StackChange, StorageChange}; use crate::smt::BitVec; use crate::stack::Stack; use crate::state::evm::EvmState; +use crate::storage::{AccountStorage, StorageValue}; use z3_ext::ast::Bool; -pub trait MachineState { +pub trait MachineState { type PC; fn pc(&self) -> Self::PC; @@ -19,20 +22,24 @@ pub trait MachineState { fn mem_read(&self, idx: Index) -> BitVec<32>; fn stack_apply(&mut self, stack_rec: StackChange); fn mem_apply(&mut self, mem_rec: MemChange); + fn storage(&self) -> &AccountStorage; + fn storage_write(&mut self, idx: Index, val: StorageValue); + fn storage_read(&self, idx: &Index) -> StorageValue; + fn storage_apply(&mut self, storage_rec: StorageChange); } -pub trait Machine { +pub trait Machine { type State: MachineState; // All possible final states - fn exec(&mut self) -> Vec; - fn pgm(&self) -> Vec; + fn exec(&mut self) -> Execution; + fn pgm(&self) -> Program; fn state(&self) -> Self::State; fn state_ref(&self) -> &Self::State; fn state_ref_mut(&mut self) -> &mut Self::State; } -pub trait MachineInstruction<'ctx, const SZ: u32> { +pub trait MachineInstruction<'ctx, const SZ: usize> { fn exec(&self, mach: &EvmState) -> MachineRecord; } diff --git a/test-contracts/.gitignore b/test-contracts/.gitignore new file mode 100644 index 0000000..85198aa --- /dev/null +++ b/test-contracts/.gitignore @@ -0,0 +1,14 @@ +# Compiler files +cache/ +out/ + +# Ignores development broadcast logs +!/broadcast +/broadcast/*/31337/ +/broadcast/**/dry-run/ + +# Docs +docs/ + +# Dotenv file +.env diff --git a/test-contracts/foundry.toml b/test-contracts/foundry.toml new file mode 100644 index 0000000..4ff40c4 --- /dev/null +++ b/test-contracts/foundry.toml @@ -0,0 +1,6 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] + +# See more config options https://github.com/foundry-rs/foundry/tree/master/config \ No newline at end of file diff --git a/test-contracts/lib/forge-std b/test-contracts/lib/forge-std new file mode 160000 index 0000000..fc560fa --- /dev/null +++ b/test-contracts/lib/forge-std @@ -0,0 +1 @@ +Subproject commit fc560fa34fa12a335a50c35d92e55a6628ca467c diff --git a/test-contracts/script/Counter.s.sol b/test-contracts/script/Counter.s.sol new file mode 100644 index 0000000..0e546ab --- /dev/null +++ b/test-contracts/script/Counter.s.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; + +contract CounterScript is Script { + function setUp() public {} + + function run() public { + vm.broadcast(); + } +} diff --git a/test-contracts/src/Counter.sol b/test-contracts/src/Counter.sol new file mode 100644 index 0000000..aded799 --- /dev/null +++ b/test-contracts/src/Counter.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract Counter { + uint256 public number; + + function setNumber(uint256 newNumber) public { + number = newNumber; + } + + function increment() public { + number++; + } +} diff --git a/test-contracts/src/SimpleToken.sol b/test-contracts/src/SimpleToken.sol new file mode 100644 index 0000000..5697241 --- /dev/null +++ b/test-contracts/src/SimpleToken.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +contract SimpleToken { + mapping(address => uint256) public balances; + + constructor() { + balances[msg.sender] = 100; + } + + function transfer(address recipient, uint256 amt) public { + require(balances[msg.sender] >= amt); + balances[msg.sender] -= amt; + balances[recipient] += amt; + } + + function getBalance(address owner) external view returns (uint256) { + return balances[owner]; + } +} diff --git a/test-contracts/src/Storage.sol b/test-contracts/src/Storage.sol new file mode 100644 index 0000000..debba3c --- /dev/null +++ b/test-contracts/src/Storage.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: AGPL-3.0 +// From https://github.com/a16z/halmos/blob/main/tests/src/Storage.sol +pragma solidity >=0.8.0 <0.9.0; + +contract Storage { + uint public num; + + mapping (uint => uint) public map1; + mapping (uint => mapping (uint => uint)) public map2; + mapping (uint => mapping (uint => mapping (uint => uint))) public map3; + + uint[] public arr1; + uint[][] public arr2; + + mapping (uint => uint[]) public map1Arr1; + + constructor () { } + + function setMap1(uint k, uint v) public { + map1[k] = v; + } + + function setMap2(uint k1, uint k2, uint v) public { + map2[k1][k2] = v; + } + + function setMap3(uint k1, uint k2, uint k3, uint v) public { + map3[k1][k2][k3] = v; + } + + function addArr1(uint v) public { + arr1.push(v); + } + + function addArr2(uint i, uint v) public { + arr2[i].push(v); + } + + function addMap1Arr1(uint k, uint v) public { + map1Arr1[k].push(v); + } +} diff --git a/test-contracts/src/StorageSimple.sol b/test-contracts/src/StorageSimple.sol new file mode 100644 index 0000000..6de7606 --- /dev/null +++ b/test-contracts/src/StorageSimple.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.3; + +contract SimpleStorage { + mapping (uint => uint) public ids; + + function set(uint key, uint val) public { + ids[key] = val; + } +} \ No newline at end of file diff --git a/test-contracts/src/VulnerableVault.sol b/test-contracts/src/VulnerableVault.sol new file mode 100644 index 0000000..dd4e40e --- /dev/null +++ b/test-contracts/src/VulnerableVault.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.8.0; + +contract Vault { + + mapping (address => uint) public credit; + + function deposit(address to) payable public{ + credit[to] += msg.value; + } + + function withdraw(uint amount) public{ + if (credit[msg.sender] >= amount) { + (bool success, ) = msg.sender.call{value: amount}(""); + require(success); + unchecked{ + credit[msg.sender] -= amount; + } + } + } + + function queryCredit(address to) view public returns(uint){ + return credit[to]; + } +} \ No newline at end of file diff --git a/test-contracts/test/Counter.t.sol b/test-contracts/test/Counter.t.sol new file mode 100644 index 0000000..30235e8 --- /dev/null +++ b/test-contracts/test/Counter.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; +import "../src/Counter.sol"; + +contract CounterTest is Test { + Counter public counter; + + function setUp() public { + counter = new Counter(); + counter.setNumber(0); + } + + function testIncrement() public { + counter.increment(); + assertEq(counter.number(), 1); + } + + function testSetNumber(uint256 x) public { + counter.setNumber(x); + assertEq(counter.number(), x); + } +} diff --git a/test-contracts/test/Storage.t.sol b/test-contracts/test/Storage.t.sol new file mode 100644 index 0000000..2be3b21 --- /dev/null +++ b/test-contracts/test/Storage.t.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: AGPL-3.0 +// From https://github.com/a16z/halmos/blob/main/tests/test/Storage.t.sol +pragma solidity >=0.8.0 <0.9.0; + + +import "forge-std/Test.sol"; +import "../src/Storage.sol"; + +contract StorageTest is Storage { + function testSetMap1(uint k, uint v) public { + setMap1(k, v); + assert(map1[k] == v); + } + + function testSetMap2(uint k1, uint k2, uint v) public { + setMap2(k1, k2, v); + assert(map2[k1][k2] == v); + } + + function testSetMap3(uint k1, uint k2, uint k3, uint v) public { + setMap3(k1, k2, k3, v); + assert(map3[k1][k2][k3] == v); + } + + function testAddArr1(uint v) public { + uint size = arr1.length; + addArr1(v); + assert(arr1.length == size + 1); + assert(arr1[size] == v); + } + + function testAddArr2(uint i, uint v) public { + uint size = arr2[i].length; + addArr2(i, v); + assert(arr2[i].length == size + 1); + assert(arr2[i][size] == v); + } + + function testAddMap1Arr1(uint k, uint v) public { + uint size = map1Arr1[k].length; + addMap1Arr1(k, v); + assert(map1Arr1[k].length == size + 1); + assert(map1Arr1[k][size] == v); + } +} \ No newline at end of file diff --git a/tests/lib.rs b/tests/lib.rs new file mode 100644 index 0000000..8bfcee6 --- /dev/null +++ b/tests/lib.rs @@ -0,0 +1,140 @@ +#![allow(unused, unused_imports)] +extern crate ser; +use ser::{ + bvc, bvi, conversion::*, machine::*, memory::*, parser::*, stack::*, storage::*, traits::*, +}; +use z3::{ast::*, SatResult}; + +pub const COUNTER_WITH_STORAGE_MAPPING: &str = r#"608060405234801561001057600080fd5b5060056000806001815260200190815260200160002081905550610197806100396000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063846719e01461003b578063d78233d61461006b575b600080fd5b6100556004803603810190610050919061010a565b61009b565b6040516100629190610146565b60405180910390f35b6100856004803603810190610080919061010a565b6100b7565b6040516100929190610146565b60405180910390f35b6000806000838152602001908152602001600020549050919050565b60006020528060005260406000206000915090505481565b600080fd5b6000819050919050565b6100e7816100d4565b81146100f257600080fd5b50565b600081359050610104816100de565b92915050565b6000602082840312156101205761011f6100cf565b5b600061012e848285016100f5565b91505092915050565b610140816100d4565b82525050565b600060208201905061015b6000830184610137565b9291505056fea2646970667358fe122066b287fef10118cba238fe38953bfefe938afefefefefe94fefe3682fefefefe64736f6c63430008110033"#; +pub const SUPERSIMPLE: &str = r#"604260005260206000F3"#; +pub const STORAGE_SIMPLE: &str = r#"6080604052348015600f57600080fd5b506004361060325760003560e01c80631ab06ee5146037578063fac333ac146056575b600080fd5b605460423660046085565b60009182526020829052604090912055565b005b6073606136600460a6565b60006020819052908152604090205481565b60405190815260200160405180910390f35b60008060408385031215609757600080fd5b50508035926020909101359150565b60006020828403121560b757600080fd5b503591905056fea26469706673582212204a6bf5c04a6e273d775914b20b0bab1bca28228be5562d496002981e13ff015264736f6c63430008130033"#; +#[test] + +fn can_run_simple_parsed_pgm() { + let pgm = Parser::with_pgm(SUPERSIMPLE).parse(); + let mut evm = Evm::new(pgm); + + { + let sat_branches = evm.exec(); + + let leaf = sat_branches.states.leaves(); + assert_eq!(1, leaf.len()); + let final_tree = leaf.first().unwrap().clone(); + let mut mem_val = final_tree.val.mem_read(bvi(0)); + mem_val.simplify(); + assert_eq!(bvi(66), mem_val); + } +} + +#[test] +fn can_run_simple_storage_pgm() { + let pgm = Parser::with_pgm(STORAGE_SIMPLE).parse(); + let mut evm = Evm::new(pgm); + + let execution = evm.exec(); + let leaf = execution.states.leaves(); + assert_eq!(2, leaf.len()); + eprintln!("LEAVES: {:#?}", leaf); + let final_tree = leaf.get(1).unwrap().clone(); + // eprintln!("FINAL TREE: {:#?}", final_tree); + let mut mem_val = final_tree.val.mem_read(bvi(64)); + mem_val.simplify(); + assert_eq!(bvi(128), mem_val); +} + +#[test] +fn can_run_counter_with_storage_mapping_pgm() { + let pgm = Parser::with_pgm(COUNTER_WITH_STORAGE_MAPPING).parse(); + let mut evm = Evm::new(pgm); + + let execution = evm.exec(); + let leaf = execution.states.leaves(); + assert_eq!(2, leaf.len()); + // eprintln!("LEAVES: {:#?}", leaf); +} + +/* +SHOULD REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +SWAP2 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0 +RETURN + + +SHOULD NOT REVERT: + +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +PUSH1 0x40 +SWAP3 +PUSH1 0x0e // 14 +JUMPI +REVERT +JUMPDEST +PUSH1 0x10 +RETURN + + +MAYBE REVERT: +PUSH1 0x42 +PUSH1 0x00 +PUSH2 0x5000 +CALLDATASIZE +PUSH1 0x0d +JUMPI +REVERT +JUMPDEST +PUSH1 0x00 +RETURN + +*/ +const SWAP2_JUMPI_REVERT: &str = r#"604260006150003691600d57fd5b6000f3"#; +const SWAP2_JUMPI_MAYBE_REVERT: &str = r#"6042600061500036600d57fd5b6000f3"#; +const SWAP3_JUMPI_RETURN_16: &str = r#"60426000615000604091600e57fd5b6000f3"#; +#[test] +fn test_swap2_jumpi_revert() { + let pgm = Parser::with_pgm(SWAP2_JUMPI_REVERT).parse(); + let mut evm = Evm::new(pgm); + let execution = evm.exec(); + eprintln!("Execution tree: {:#?}", execution.states.clone()); + // Should have two paths: one reachable and one not. The reachable path should be the one in which there is a revert + let reachability_report = Evm::exec_check(execution); + assert_eq!(2, reachability_report.len()); + assert_eq!( + SatResult::Sat, + reachability_report.first().unwrap().1.unwrap() + ); + assert_eq!( + SatResult::Unsat, + reachability_report.get(1).unwrap().1.unwrap() + ); +} + +#[test] +fn test_swap2_jumpi_maybe_revert() { + let pgm = Parser::with_pgm(SWAP2_JUMPI_MAYBE_REVERT).parse(); + let mut evm = Evm::new(pgm); + let execution = evm.exec(); + eprintln!("Execution tree: {:#?}", execution.states.clone()); + // Should have two paths: both reachable. The first reachable path is the one in which calldata is zero and there is a revert. + // The second reachable path is the one in which calldata is not zero and there is not a revert. + let reachability_report = Evm::exec_check(execution); + assert_eq!(2, reachability_report.len()); + assert_eq!( + SatResult::Sat, + reachability_report.first().unwrap().1.unwrap() + ); + assert_eq!( + SatResult::Sat, + reachability_report.get(1).unwrap().1.unwrap() + ); +}