git.delta.rocks / unique-network / refs/commits / d11053909f47

difftreelog

refactor move evm-coder out of the repo

Yaroslav Bolyukin2023-02-05parent: #8dd063b.patch.diff
in: master

51 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -172,9 +172,9 @@
 
 [[package]]
 name = "anyhow"
-version = "1.0.68"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
+checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
 
 [[package]]
 name = "app-promotion-rpc"
@@ -343,9 +343,9 @@
 
 [[package]]
 name = "async-trait"
-version = "0.1.63"
+version = "0.1.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1"
+checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -706,20 +706,9 @@
 
 [[package]]
 name = "bstr"
-version = "0.2.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
-dependencies = [
- "lazy_static",
- "memchr",
- "regex-automata",
-]
-
-[[package]]
-name = "bstr"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b"
+checksum = "b7f0778972c64420fdedc63f09919c8a88bda7b25135357fd25a5d9f3257e832"
 dependencies = [
  "memchr",
  "serde",
@@ -760,9 +749,9 @@
 
 [[package]]
 name = "bytes"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
 [[package]]
 name = "bzip2-sys"
@@ -808,9 +797,9 @@
 
 [[package]]
 name = "cc"
-version = "1.0.78"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 dependencies = [
  "jobserver",
 ]
@@ -1027,18 +1016,6 @@
 ]
 
 [[package]]
-name = "console"
-version = "0.15.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60"
-dependencies = [
- "encode_unicode",
- "lazy_static",
- "libc",
- "windows-sys 0.42.0",
-]
-
-[[package]]
 name = "const-oid"
 version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1221,9 +1198,9 @@
 
 [[package]]
 name = "crc"
-version = "3.0.0"
+version = "3.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "53757d12b596c16c78b83458d732a5d1a17ab3f53f2f7412f6fb57cc8a140ab3"
+checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe"
 dependencies = [
  "crc-catalog",
 ]
@@ -1874,9 +1851,9 @@
 
 [[package]]
 name = "curve25519-dalek"
-version = "4.0.0-pre.5"
+version = "4.0.0-rc.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67bc65846be335cb20f4e52d49a437b773a2c1fdb42b19fc84e79e6f6771536f"
+checksum = "8da00a7a9a4eb92a0a0f8e75660926d48f0d0f3c537e455c457bcdaa1e16b1ac"
 dependencies = [
  "cfg-if",
  "fiat-crypto",
@@ -1888,9 +1865,9 @@
 
 [[package]]
 name = "cxx"
-version = "1.0.87"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b61a7545f753a88bcbe0a70de1fcc0221e10bfc752f576754fa91e663db1622e"
+checksum = "bc831ee6a32dd495436e317595e639a587aa9907bef96fe6e6abc290ab6204e9"
 dependencies = [
  "cc",
  "cxxbridge-flags",
@@ -1900,9 +1877,9 @@
 
 [[package]]
 name = "cxx-build"
-version = "1.0.87"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f464457d494b5ed6905c63b0c4704842aba319084a0a3561cdc1359536b53200"
+checksum = "94331d54f1b1a8895cd81049f7eaaaef9d05a7dcb4d1fd08bf3ff0806246789d"
 dependencies = [
  "cc",
  "codespan-reporting",
@@ -1915,15 +1892,15 @@
 
 [[package]]
 name = "cxxbridge-flags"
-version = "1.0.87"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43c7119ce3a3701ed81aca8410b9acf6fc399d2629d057b87e2efa4e63a3aaea"
+checksum = "48dcd35ba14ca9b40d6e4b4b39961f23d835dbb8eed74565ded361d93e1feb8a"
 
 [[package]]
 name = "cxxbridge-macro"
-version = "1.0.87"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65e07508b90551e610910fa648a1878991d367064997a596135b86df30daf07e"
+checksum = "81bbeb29798b407ccd82a3324ade1a7286e0d29851475990b612670f6f5124d2"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2268,9 +2245,9 @@
 
 [[package]]
 name = "either"
-version = "1.8.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
 name = "elliptic-curve"
@@ -2295,12 +2272,6 @@
 ]
 
 [[package]]
-name = "encode_unicode"
-version = "0.3.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
-
-[[package]]
 name = "enum-as-inner"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2474,24 +2445,20 @@
 
 [[package]]
 name = "evm-coder"
-version = "0.1.6"
+version = "0.3.0"
+source = "git+https://github.com/uniquenetwork/evm-coder?tag=v0.3.0#c4bfdf39d84fbe74c6178417177f2a7f81d92bdd"
 dependencies = [
  "ethereum",
  "evm-coder-procedural",
- "evm-core",
- "frame-support",
- "hex",
- "hex-literal",
  "impl-trait-for-tuples",
  "primitive-types",
  "sha3-const",
- "similar-asserts",
- "trybuild",
 ]
 
 [[package]]
 name = "evm-coder-procedural"
-version = "0.2.3"
+version = "0.3.0"
+source = "git+https://github.com/uniquenetwork/evm-coder?tag=v0.3.0#c4bfdf39d84fbe74c6178417177f2a7f81d92bdd"
 dependencies = [
  "Inflector",
  "hex",
@@ -2502,6 +2469,15 @@
 ]
 
 [[package]]
+name = "evm-coder-substrate-procedural"
+version = "0.1.0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "evm-core"
 version = "0.37.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3227,9 +3203,9 @@
 
 [[package]]
 name = "fs_extra"
-version = "1.2.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2022715d62ab30faffd124d40b76f4134a550a87792276512b18d63272333394"
+checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
 
 [[package]]
 name = "funty"
@@ -3239,9 +3215,9 @@
 
 [[package]]
 name = "futures"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
+checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -3254,9 +3230,9 @@
 
 [[package]]
 name = "futures-channel"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
+checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -3264,15 +3240,15 @@
 
 [[package]]
 name = "futures-core"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
+checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
+checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -3282,9 +3258,9 @@
 
 [[package]]
 name = "futures-io"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
+checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
 
 [[package]]
 name = "futures-lite"
@@ -3303,9 +3279,9 @@
 
 [[package]]
 name = "futures-macro"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
+checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3325,15 +3301,15 @@
 
 [[package]]
 name = "futures-sink"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
+checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
 
 [[package]]
 name = "futures-task"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
+checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
 
 [[package]]
 name = "futures-timer"
@@ -3343,9 +3319,9 @@
 
 [[package]]
 name = "futures-util"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
+checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -3469,7 +3445,7 @@
 checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
 dependencies = [
  "aho-corasick",
- "bstr 1.1.0",
+ "bstr",
  "fnv",
  "log",
  "regex",
@@ -3545,9 +3521,9 @@
 
 [[package]]
 name = "heck"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
@@ -3568,6 +3544,12 @@
 ]
 
 [[package]]
+name = "hermit-abi"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "856b5cb0902c2b6d65d5fd97dfa30f9b70c7538e770b98eab5ed52d8db923e01"
+
+[[package]]
 name = "hex"
 version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3697,9 +3679,9 @@
 
 [[package]]
 name = "hyper"
-version = "0.14.23"
+version = "0.14.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
+checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -3914,12 +3896,12 @@
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
+checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
 dependencies = [
  "libc",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -3948,14 +3930,14 @@
 
 [[package]]
 name = "is-terminal"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
+checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef"
 dependencies = [
- "hermit-abi 0.2.6",
- "io-lifetimes 1.0.4",
- "rustix 0.36.7",
- "windows-sys 0.42.0",
+ "hermit-abi 0.3.0",
+ "io-lifetimes 1.0.5",
+ "rustix 0.36.8",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -3984,9 +3966,9 @@
 
 [[package]]
 name = "js-sys"
-version = "0.3.60"
+version = "0.3.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -4974,7 +4956,7 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b20a59d985586e4a5aef64564ac77299f8586d8be6cf9106a5a40207e8908efb"
 dependencies = [
- "rustix 0.36.7",
+ "rustix 0.36.8",
 ]
 
 [[package]]
@@ -5284,9 +5266,9 @@
 
 [[package]]
 name = "netlink-packet-utils"
-version = "0.5.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25af9cf0dc55498b7bd94a1508af7a78706aa0ab715a73c5169273e03c84845e"
+checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34"
 dependencies = [
  "anyhow",
  "byteorder",
@@ -6248,6 +6230,8 @@
 version = "0.1.3"
 dependencies = [
  "evm-coder",
+ "evm-coder-substrate-procedural",
+ "evm-core",
  "frame-benchmarking",
  "frame-support",
  "frame-system",
@@ -6256,6 +6240,7 @@
  "scale-info",
  "sp-core",
  "sp-std",
+ "spez",
  "up-data-structs",
 ]
 
@@ -7272,9 +7257,9 @@
 
 [[package]]
 name = "parity-scale-codec"
-version = "3.2.2"
+version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ab01d0f889e957861bc65888d5ccbe82c158d0270136ba46820d43837cdf72"
+checksum = "c3840933452adf7b3b9145e27086a5a3376c619dca1a21b1e5a5af0d54979bed"
 dependencies = [
  "arrayvec 0.7.2",
  "bitvec",
@@ -7333,7 +7318,7 @@
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.6",
+ "parking_lot_core 0.9.7",
 ]
 
 [[package]]
@@ -7352,15 +7337,15 @@
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.6"
+version = "0.9.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -8838,10 +8823,16 @@
 ]
 
 [[package]]
+name = "proc-macro-hack"
+version = "0.5.20+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
+
+[[package]]
 name = "proc-macro2"
-version = "1.0.50"
+version = "1.0.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
+checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
 dependencies = [
  "unicode-ident",
 ]
@@ -9675,16 +9666,16 @@
 
 [[package]]
 name = "rustix"
-version = "0.36.7"
+version = "0.36.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
+checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
 dependencies = [
  "bitflags",
  "errno",
- "io-lifetimes 1.0.4",
+ "io-lifetimes 1.0.5",
  "libc",
  "linux-raw-sys 0.1.4",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -10996,9 +10987,9 @@
 
 [[package]]
 name = "security-framework"
-version = "2.8.1"
+version = "2.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c4437699b6d34972de58652c68b98cb5b53a4199ab126db8e20ec8ded29a721"
+checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
 dependencies = [
  "bitflags",
  "core-foundation",
@@ -11072,9 +11063,9 @@
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.92"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a"
 dependencies = [
  "itoa",
  "ryu",
@@ -11206,26 +11197,6 @@
 ]
 
 [[package]]
-name = "similar"
-version = "2.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf"
-dependencies = [
- "bstr 0.2.17",
- "unicode-segmentation",
-]
-
-[[package]]
-name = "similar-asserts"
-version = "1.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18"
-dependencies = [
- "console",
- "similar",
-]
-
-[[package]]
 name = "slab"
 version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -11275,14 +11246,14 @@
 
 [[package]]
 name = "snow"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "774d05a3edae07ce6d68ea6984f3c05e9bba8927e3dd591e3b479e5b03213d0d"
+checksum = "12ba5f4d4ff12bdb6a169ed51b7c48c0e0ac4b0b4b31012b2571e97d78d3201d"
 dependencies = [
  "aes-gcm 0.9.4",
  "blake2",
  "chacha20poly1305",
- "curve25519-dalek 4.0.0-pre.5",
+ "curve25519-dalek 4.0.0-rc.0",
  "rand_core 0.6.4",
  "ring",
  "rustc_version 0.4.0",
@@ -12031,6 +12002,28 @@
 ]
 
 [[package]]
+name = "spez"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "304d2fd6a79879f77b207ba8cd5079c22f872eaad65a3fb8d71799e5bacf368b"
+dependencies = [
+ "proc-macro-hack",
+ "spez-macros",
+]
+
+[[package]]
+name = "spez-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7fa06037d8ccb6cdadc151129062ebc9e4281c1ea44b2c704582245d017d1dc"
+dependencies = [
+ "proc-macro-hack",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "spin"
 version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -12612,15 +12605,15 @@
 
 [[package]]
 name = "tinyvec_macros"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.24.2"
+version = "1.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb"
+checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
 dependencies = [
  "autocfg",
  "bytes",
@@ -12702,9 +12695,9 @@
 
 [[package]]
 name = "toml_edit"
-version = "0.18.0"
+version = "0.18.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "729bfd096e40da9c001f778f5cdecbd2957929a24e10e5883d9392220a751581"
+checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b"
 dependencies = [
  "indexmap",
  "nom8",
@@ -12976,21 +12969,6 @@
  "sp-weights",
  "substrate-rpc-client",
  "zstd",
-]
-
-[[package]]
-name = "trybuild"
-version = "1.0.76"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ed2c57956f91546d4d33614265a85d55c8e1ab91484853a10335894786d7db6"
-dependencies = [
- "glob",
- "once_cell",
- "serde",
- "serde_derive",
- "serde_json",
- "termcolor",
- "toml",
 ]
 
 [[package]]
@@ -13108,12 +13086,6 @@
 dependencies = [
  "tinyvec",
 ]
-
-[[package]]
-name = "unicode-segmentation"
-version = "1.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
 
 [[package]]
 name = "unicode-width"
@@ -13446,9 +13418,9 @@
 
 [[package]]
 name = "uuid"
-version = "1.2.2"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
+checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
 dependencies = [
  "getrandom 0.2.8",
 ]
@@ -13543,9 +13515,9 @@
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -13553,9 +13525,9 @@
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
 dependencies = [
  "bumpalo",
  "log",
@@ -13568,9 +13540,9 @@
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.33"
+version = "0.4.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
+checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -13580,9 +13552,9 @@
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -13590,9 +13562,9 @@
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -13603,9 +13575,9 @@
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
 
 [[package]]
 name = "wasm-instrument"
@@ -13886,9 +13858,9 @@
 
 [[package]]
 name = "web-sys"
-version = "0.3.60"
+version = "0.3.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -14338,6 +14310,30 @@
 ]
 
 [[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.1",
+ "windows_i686_gnu 0.42.1",
+ "windows_i686_msvc 0.42.1",
+ "windows_x86_64_gnu 0.42.1",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.1",
+]
+
+[[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -14644,9 +14640,9 @@
 
 [[package]]
 name = "zstd-sys"
-version = "2.0.5+zstd.1.5.2"
+version = "2.0.6+zstd.1.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "edc50ffce891ad571e9f9afe5039c4837bede781ac4bb13052ed7ae695518596"
+checksum = "68a3f9792c0c3dc6c165840a75f47ae1f4da402c2d006881129579f6597e801b"
 dependencies = [
  "cc",
  "libc",
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -19,7 +19,7 @@
 
 [workspace.dependencies]
 # Unique
-evm-coder = { default-features = false, path = "crates/evm-coder" }
+evm-coder = { git = "https://github.com/uniquenetwork/evm-coder", tag = "v0.3.0", default-features = false }
 struct-versioning = { path = "crates/struct-versioning" }
 precompile-utils-macro = { path = "runtime/common/ethereum/precompiles/utils/macro" }
 up-common = { path = "primitives/common", default-features = false }
deletedcrates/evm-coder/CHANGELOG.mddiffbeforeafterboth
--- a/crates/evm-coder/CHANGELOG.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Change Log
-
-All notable changes to this project will be documented in this file.
-
-<!-- bureaucrate goes here -->
-## [v0.1.6] - 2023-01-12
-
-### Added
-- Support Option<T> type.
-### Removed
-- Frontier dependency.
-
-## [v0.1.5] - 2022-11-30
-
-### Added
-- Derive macro to support structures and enums.
-
-## [v0.1.4] - 2022-11-02
-
-### Added
-
-- Named structures support.
-
-## [v0.1.3] - 2022-08-29
-
-### Fixed
-
-- Parsing simple values.
-
-## [v0.1.2] 2022-08-19
-
-### Added
-
-- Implementation `AbiWrite` for tuples.
-
-### Fixes
-
-- Tuple generation for solidity.
-
-## [v0.1.1] 2022-08-16
-
-### Other changes
-
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
deletedcrates/evm-coder/Cargo.tomldiffbeforeafterboth
--- a/crates/evm-coder/Cargo.toml
+++ /dev/null
@@ -1,32 +0,0 @@
-[package]
-edition = "2021"
-license = "GPLv3"
-name = "evm-coder"
-version = "0.1.6"
-
-[dependencies]
-sha3-const = { version = "0.1.1", default-features = false }
-# evm-coder reexports those proc-macro
-evm-coder-procedural = { path = "./procedural" }
-# Evm uses primitive-types for H160, H256 and others
-primitive-types = { workspace = true }
-# Evm doesn't have reexports for log and others
-ethereum = { workspace = true }
-frame-support = { workspace = true }
-# Error types for execution
-evm-core = { workspace = true }
-# We have tuple-heavy code in solidity.rs
-impl-trait-for-tuples = { workspace = true }
-
-[dev-dependencies]
-# We want to assert some large binary blobs equality in tests
-hex = "0.4.3"
-hex-literal = { workspace = true }
-similar-asserts = "1.4.2"
-trybuild = "1.0"
-
-[features]
-default = ["std"]
-std = ["ethereum/std", "evm-core/std", "frame-support/std", "primitive-types/std"]
-# Stub/interface generation
-stubgen = []
deletedcrates/evm-coder/README.mddiffbeforeafterboth
--- a/crates/evm-coder/README.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# evm-coder
-
-Library for seamless call translation between Rust and Solidity code
-
-By encoding solidity definitions in Rust, this library also provides generation of
-solidity interfaces for ethereum developers
-
-## Overview
-
-Most of this library functionality shouldn't be used directly, but via macros
-
-- [`solidity_interface`]
-- [`ToLog`]
-
-<!-- TODO: make links useable on github, by publishing crate to docs.rs, and linking it from here instead -->
\ No newline at end of file
deletedcrates/evm-coder/procedural/Cargo.tomldiffbeforeafterboth
--- a/crates/evm-coder/procedural/Cargo.toml
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-edition = "2021"
-license = "GPLv3"
-name = "evm-coder-procedural"
-version = "0.2.3"
-
-[lib]
-proc-macro = true
-
-[dependencies]
-# Ethereum uses keccak (=sha3) for selectors
-sha3 = "0.10.1"
-# Value formatting
-Inflector = "0.11.4"
-hex = "0.4.3"
-# General proc-macro utilities
-proc-macro2 = "1.0"
-quote = "1.0"
-syn = { version = "1.0", features = ["full"] }
deletedcrates/evm-coder/procedural/src/abi_derive/derive_enum.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive/derive_enum.rs
+++ /dev/null
@@ -1,199 +0,0 @@
-use quote::quote;
-
-use super::extract_docs;
-
-pub fn impl_solidity_option<'a>(
-	docs: Vec<String>,
-	name: &proc_macro2::Ident,
-	enum_options: impl Iterator<Item = &'a syn::Variant> + Clone,
-) -> proc_macro2::TokenStream {
-	let variant_names = enum_options.clone().map(|opt| {
-		let opt = &opt.ident;
-		let s = name.to_string() + "." + opt.to_string().as_str();
-		let as_string = proc_macro2::Literal::string(s.as_str());
-		quote!(#name::#opt => #as_string,)
-	});
-	let solidity_name = name.to_string();
-
-	let solidity_fields = enum_options.map(|v| {
-		let docs = extract_docs(&v.attrs).expect("TODO: handle bad docs");
-		let name = v.ident.to_string();
-		quote! {
-			SolidityEnumVariant {
-				docs: &[#(#docs),*],
-				name: #name,
-			}
-		}
-	});
-
-	quote!(
-		#[cfg(feature = "stubgen")]
-		impl ::evm_coder::solidity::SolidityEnumTy for #name {
-			fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector) -> String {
-				use evm_coder::solidity::*;
-				use core::fmt::Write;
-				let interface = SolidityEnum {
-					docs: &[#(#docs),*],
-					name: #solidity_name,
-					fields: &[#(
-						#solidity_fields,
-					)*],
-				};
-				let mut out = String::new();
-				let _ = interface.format(&mut out, tc);
-				tc.collect(out);
-				#solidity_name.to_string()
-			}
-			fn solidity_option(&self) -> &str {
-				match self {
-					#(#variant_names)*
-				}
-			}
-		}
-	)
-}
-
-pub fn impl_enum_from_u8<'a>(
-	name: &proc_macro2::Ident,
-	enum_options: impl Iterator<Item = &'a syn::Variant>,
-) -> proc_macro2::TokenStream {
-	let error_str = format!("Value not convertible into enum \"{name}\"");
-	let error_str = proc_macro2::Literal::string(&error_str);
-	let enum_options = enum_options.enumerate().map(|(i, opt)| {
-		let opt = &opt.ident;
-		let n = proc_macro2::Literal::u8_suffixed(i as u8);
-		quote! {#n => Ok(#name::#opt),}
-	});
-
-	quote!(
-		impl TryFrom<u8> for #name {
-			type Error = &'static str;
-
-			fn try_from(value: u8) -> ::core::result::Result<Self, Self::Error> {
-				const err: &'static str = #error_str;
-				match value {
-					#(#enum_options)*
-					_ => Err(err)
-				}
-			}
-		}
-	)
-}
-
-pub fn impl_enum_abi_type(name: &syn::Ident) -> proc_macro2::TokenStream {
-	quote! {
-		impl ::evm_coder::abi::AbiType for #name {
-			const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <u8 as ::evm_coder::abi::AbiType>::SIGNATURE;
-
-			fn is_dynamic() -> bool {
-				<u8 as ::evm_coder::abi::AbiType>::is_dynamic()
-			}
-			fn size() -> usize {
-				<u8 as ::evm_coder::abi::AbiType>::size()
-			}
-		}
-	}
-}
-
-pub fn impl_enum_abi_read(name: &syn::Ident) -> proc_macro2::TokenStream {
-	quote!(
-		impl ::evm_coder::abi::AbiRead for #name {
-			fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Self> {
-				Ok(
-					<u8 as ::evm_coder::abi::AbiRead>::abi_read(reader)?
-						.try_into()?
-				)
-			}
-		}
-	)
-}
-
-pub fn impl_enum_abi_write(name: &syn::Ident) -> proc_macro2::TokenStream {
-	quote!(
-		impl ::evm_coder::abi::AbiWrite for #name {
-			fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) {
-				::evm_coder::abi::AbiWrite::abi_write(&(*self as u8), writer);
-			}
-		}
-	)
-}
-
-pub fn impl_enum_solidity_type_name(name: &syn::Ident) -> proc_macro2::TokenStream {
-	quote!(
-		#[cfg(feature = "stubgen")]
-		impl ::evm_coder::solidity::SolidityTypeName for #name {
-			fn solidity_name(
-				writer: &mut impl ::core::fmt::Write,
-				tc: &::evm_coder::solidity::TypeCollector,
-			) -> ::core::fmt::Result {
-				write!(writer, "{}", tc.collect_enum::<Self>())
-			}
-
-			fn is_simple() -> bool {
-				true
-			}
-
-			fn solidity_default(
-				writer: &mut impl ::core::fmt::Write,
-				tc: &::evm_coder::solidity::TypeCollector,
-			) -> ::core::fmt::Result {
-				write!(writer, "{}", <#name as ::evm_coder::solidity::SolidityEnumTy>::solidity_option(&<#name>::default()))
-			}
-		}
-	)
-}
-
-pub fn check_enum_fields(de: &syn::DataEnum) -> syn::Result<()> {
-	for v in de.variants.iter() {
-		if !v.fields.is_empty() {
-			return Err(syn::Error::new(
-				v.ident.span(),
-				"Enumeration parameters should not have fields",
-			));
-		} else if v.discriminant.is_some() {
-			return Err(syn::Error::new(
-				v.ident.span(),
-				"Enumeration options should not have an explicit specified value",
-			));
-		}
-	}
-
-	Ok(())
-}
-
-pub fn check_repr_u8(name: &syn::Ident, attrs: &[syn::Attribute]) -> syn::Result<()> {
-	let mut has_repr = false;
-	for attr in attrs.iter() {
-		if attr.path.is_ident("repr") {
-			has_repr = true;
-			let meta = attr.parse_meta()?;
-			check_meta_u8(&meta)?;
-		}
-	}
-
-	if !has_repr {
-		return Err(syn::Error::new(name.span(), "Enum is not \"repr(u8)\""));
-	}
-
-	Ok(())
-}
-
-fn check_meta_u8(meta: &syn::Meta) -> Result<(), syn::Error> {
-	if let syn::Meta::List(p) = meta {
-		for nm in p.nested.iter() {
-			if let syn::NestedMeta::Meta(syn::Meta::Path(p)) = nm {
-				if !p.is_ident("u8") {
-					return Err(syn::Error::new(
-						p.segments
-							.first()
-							.expect("repr segments are empty")
-							.ident
-							.span(),
-						"Enum is not \"repr(u8)\"",
-					));
-				}
-			}
-		}
-	}
-	Ok(())
-}
deletedcrates/evm-coder/procedural/src/abi_derive/derive_struct.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive/derive_struct.rs
+++ /dev/null
@@ -1,231 +0,0 @@
-use super::extract_docs;
-use quote::quote;
-use syn::Field;
-
-pub fn tuple_type<'a>(
-	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
-) -> proc_macro2::TokenStream {
-	let field_types = field_types.map(|ty| quote!(#ty,));
-	quote! {(#(#field_types)*)}
-}
-
-pub fn tuple_ref_type<'a>(
-	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
-) -> proc_macro2::TokenStream {
-	let field_types = field_types.map(|ty| quote!(&#ty,));
-	quote! {(#(#field_types)*)}
-}
-
-pub fn tuple_data_as_ref(
-	is_named_fields: bool,
-	field_names: impl Iterator<Item = syn::Ident> + Clone,
-) -> proc_macro2::TokenStream {
-	let field_names = field_names.enumerate().map(|(i, field)| {
-		if is_named_fields {
-			quote!(&self.#field,)
-		} else {
-			let field = proc_macro2::Literal::usize_unsuffixed(i);
-			quote!(&self.#field,)
-		}
-	});
-	quote! {(#(#field_names)*)}
-}
-
-pub fn tuple_names(
-	is_named_fields: bool,
-	field_names: impl Iterator<Item = syn::Ident> + Clone,
-) -> proc_macro2::TokenStream {
-	let field_names = field_names.enumerate().map(|(i, field)| {
-		if is_named_fields {
-			quote!(#field,)
-		} else {
-			let field = proc_macro2::Ident::new(
-				format!("field{}", i).as_str(),
-				proc_macro2::Span::call_site(),
-			);
-			quote!(#field,)
-		}
-	});
-	quote! {(#(#field_names)*)}
-}
-
-pub fn struct_from_tuple(
-	name: &syn::Ident,
-	is_named_fields: bool,
-	field_names: impl Iterator<Item = syn::Ident> + Clone,
-) -> proc_macro2::TokenStream {
-	let field_names = field_names.enumerate().map(|(i, field)| {
-		if is_named_fields {
-			quote!(#field,)
-		} else {
-			let field = proc_macro2::Ident::new(
-				format!("field{}", i).as_str(),
-				proc_macro2::Span::call_site(),
-			);
-			quote!(#field,)
-		}
-	});
-
-	if is_named_fields {
-		quote! {#name {#(#field_names)*}}
-	} else {
-		quote! {#name (#(#field_names)*)}
-	}
-}
-
-pub fn map_field_to_name(field: (usize, &syn::Field)) -> syn::Ident {
-	match field.1.ident.as_ref() {
-		Some(name) => name.clone(),
-		None => {
-			let mut name = "field".to_string();
-			name.push_str(field.0.to_string().as_str());
-			syn::Ident::new(name.as_str(), proc_macro2::Span::call_site())
-		}
-	}
-}
-
-pub fn map_field_to_type(field: &syn::Field) -> &syn::Type {
-	&field.ty
-}
-
-pub fn impl_can_be_placed_in_vec(ident: &syn::Ident) -> proc_macro2::TokenStream {
-	quote! {
-		impl ::evm_coder::sealed::CanBePlacedInVec for #ident {}
-	}
-}
-
-pub fn impl_struct_abi_type(
-	name: &syn::Ident,
-	tuple_type: proc_macro2::TokenStream,
-) -> proc_macro2::TokenStream {
-	quote! {
-		impl ::evm_coder::abi::AbiType for #name {
-			const SIGNATURE: ::evm_coder::custom_signature::SignatureUnit = <#tuple_type as ::evm_coder::abi::AbiType>::SIGNATURE;
-			fn is_dynamic() -> bool {
-				<#tuple_type as ::evm_coder::abi::AbiType>::is_dynamic()
-			}
-			fn size() -> usize {
-				<#tuple_type as ::evm_coder::abi::AbiType>::size()
-			}
-		}
-	}
-}
-
-pub fn impl_struct_abi_read(
-	name: &syn::Ident,
-	tuple_type: proc_macro2::TokenStream,
-	tuple_names: proc_macro2::TokenStream,
-	struct_from_tuple: proc_macro2::TokenStream,
-) -> proc_macro2::TokenStream {
-	quote!(
-		impl ::evm_coder::abi::AbiRead for #name {
-			fn abi_read(reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Self> {
-				let #tuple_names = <#tuple_type as ::evm_coder::abi::AbiRead>::abi_read(reader)?;
-				Ok(#struct_from_tuple)
-			}
-		}
-	)
-}
-
-pub fn impl_struct_abi_write(
-	name: &syn::Ident,
-	_is_named_fields: bool,
-	tuple_type: proc_macro2::TokenStream,
-	tuple_data: proc_macro2::TokenStream,
-) -> proc_macro2::TokenStream {
-	quote!(
-		impl ::evm_coder::abi::AbiWrite for #name {
-			fn abi_write(&self, writer: &mut ::evm_coder::abi::AbiWriter) {
-				<#tuple_type as ::evm_coder::abi::AbiWrite>::abi_write(&#tuple_data, writer)
-			}
-		}
-	)
-}
-
-pub fn impl_struct_solidity_type<'a>(
-	name: &syn::Ident,
-	docs: Vec<String>,
-	fields: impl Iterator<Item = &'a Field> + Clone,
-) -> proc_macro2::TokenStream {
-	let solidity_name = name.to_string();
-	let solidity_fields = fields.enumerate().map(|(i, f)| {
-		let name = f
-			.ident
-			.as_ref()
-			.map(|i| i.to_string())
-			.unwrap_or_else(|| format!("field_{i}"));
-		let ty = &f.ty;
-		let docs = extract_docs(&f.attrs).expect("TODO: handle bad docs");
-		quote! {
-			SolidityStructField::<#ty> {
-				docs: &[#(#docs),*],
-				name: #name,
-				ty: ::core::marker::PhantomData,
-			}
-		}
-	});
-	quote! {
-		#[cfg(feature = "stubgen")]
-		impl ::evm_coder::solidity::SolidityStructTy for #name {
-			/// Generate solidity definitions for methods described in this struct
-			fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector) -> String {
-				use evm_coder::solidity::*;
-				use core::fmt::Write;
-				let interface = SolidityStruct {
-					docs: &[#(#docs),*],
-					name: #solidity_name,
-					fields: (#(
-						#solidity_fields,
-					)*),
-				};
-				let mut out = String::new();
-				let _ = interface.format(&mut out, tc);
-				tc.collect(out);
-				#solidity_name.to_string()
-			}
-		}
-	}
-}
-
-pub fn impl_struct_solidity_type_name<'a>(
-	name: &syn::Ident,
-	field_types: impl Iterator<Item = &'a syn::Type> + Clone,
-	params_count: usize,
-) -> proc_macro2::TokenStream {
-	let arg_dafaults = field_types.enumerate().map(|(i, ty)| {
-		let mut defult_value = quote!(<#ty as ::evm_coder::solidity::SolidityTypeName
-			>::solidity_default(writer, tc)?;);
-		let last_item = params_count - 1;
-		if i != last_item {
-			defult_value.extend(quote! {write!(writer, ",")?;})
-		}
-		defult_value
-	});
-
-	quote! {
-		#[cfg(feature = "stubgen")]
-		impl ::evm_coder::solidity::SolidityTypeName for #name {
-			fn solidity_name(
-				writer: &mut impl ::core::fmt::Write,
-				tc: &::evm_coder::solidity::TypeCollector,
-			) -> ::core::fmt::Result {
-				write!(writer, "{}", tc.collect_struct::<Self>())
-			}
-
-			fn is_simple() -> bool {
-				false
-			}
-
-			fn solidity_default(
-				writer: &mut impl ::core::fmt::Write,
-				tc: &::evm_coder::solidity::TypeCollector,
-			) -> ::core::fmt::Result {
-				write!(writer, "{}(", tc.collect_struct::<Self>())?;
-
-				#(#arg_dafaults)*
-
-				write!(writer, ")")
-			}
-		}
-	}
-}
deletedcrates/evm-coder/procedural/src/abi_derive/mod.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/abi_derive/mod.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-mod derive_enum;
-mod derive_struct;
-
-use quote::quote;
-use derive_struct::*;
-use derive_enum::*;
-
-pub(crate) fn impl_abi_macro(ast: &syn::DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
-	let name = &ast.ident;
-	match &ast.data {
-		syn::Data::Struct(ds) => expand_struct(ds, ast),
-		syn::Data::Enum(de) => expand_enum(de, ast),
-		syn::Data::Union(_) => Err(syn::Error::new(name.span(), "Unions not supported")),
-	}
-}
-
-fn expand_struct(
-	ds: &syn::DataStruct,
-	ast: &syn::DeriveInput,
-) -> syn::Result<proc_macro2::TokenStream> {
-	let name = &ast.ident;
-	let docs = extract_docs(&ast.attrs)?;
-	let (is_named_fields, field_names, field_types, params_count) = match ds.fields {
-		syn::Fields::Named(ref fields) => Ok((
-			true,
-			fields.named.iter().enumerate().map(map_field_to_name),
-			fields.named.iter().map(map_field_to_type),
-			fields.named.len(),
-		)),
-		syn::Fields::Unnamed(ref fields) => Ok((
-			false,
-			fields.unnamed.iter().enumerate().map(map_field_to_name),
-			fields.unnamed.iter().map(map_field_to_type),
-			fields.unnamed.len(),
-		)),
-		syn::Fields::Unit => Err(syn::Error::new(name.span(), "Unit structs not supported")),
-	}?;
-
-	if params_count == 0 {
-		return Err(syn::Error::new(name.span(), "Empty structs not supported"));
-	};
-
-	let tuple_type = tuple_type(field_types.clone());
-	let tuple_ref_type = tuple_ref_type(field_types.clone());
-	let tuple_data = tuple_data_as_ref(is_named_fields, field_names.clone());
-	let tuple_names = tuple_names(is_named_fields, field_names.clone());
-	let struct_from_tuple = struct_from_tuple(name, is_named_fields, field_names.clone());
-
-	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
-	let abi_type = impl_struct_abi_type(name, tuple_type.clone());
-	let abi_read = impl_struct_abi_read(name, tuple_type, tuple_names, struct_from_tuple);
-	let abi_write = impl_struct_abi_write(name, is_named_fields, tuple_ref_type, tuple_data);
-	let solidity_type = impl_struct_solidity_type(name, docs, ds.fields.iter());
-	let solidity_type_name =
-		impl_struct_solidity_type_name(name, field_types.clone(), params_count);
-
-	Ok(quote! {
-		#can_be_plcaed_in_vec
-		#abi_type
-		#abi_read
-		#abi_write
-		#solidity_type
-		#solidity_type_name
-	})
-}
-
-fn expand_enum(
-	de: &syn::DataEnum,
-	ast: &syn::DeriveInput,
-) -> syn::Result<proc_macro2::TokenStream> {
-	let name = &ast.ident;
-	check_repr_u8(name, &ast.attrs)?;
-	check_enum_fields(de)?;
-	let docs = extract_docs(&ast.attrs)?;
-	let enum_options = de.variants.iter();
-
-	let from = impl_enum_from_u8(name, enum_options.clone());
-	let solidity_option = impl_solidity_option(docs, name, enum_options.clone());
-	let can_be_plcaed_in_vec = impl_can_be_placed_in_vec(name);
-	let abi_type = impl_enum_abi_type(name);
-	let abi_read = impl_enum_abi_read(name);
-	let abi_write = impl_enum_abi_write(name);
-	let solidity_type_name = impl_enum_solidity_type_name(name);
-
-	Ok(quote! {
-		#from
-		#solidity_option
-		#can_be_plcaed_in_vec
-		#abi_type
-		#abi_read
-		#abi_write
-		#solidity_type_name
-	})
-}
-
-fn extract_docs(attrs: &[syn::Attribute]) -> syn::Result<Vec<String>> {
-	attrs
-		.iter()
-		.filter_map(|attr| {
-			if let Some(ps) = attr.path.segments.first() {
-				if ps.ident == "doc" {
-					let meta = match attr.parse_meta() {
-						Ok(meta) => meta,
-						Err(e) => return Some(Err(e)),
-					};
-					match meta {
-						syn::Meta::NameValue(mnv) => match &mnv.lit {
-							syn::Lit::Str(ls) => return Some(Ok(ls.value())),
-							_ => unreachable!(),
-						},
-						_ => unreachable!(),
-					}
-				}
-			}
-			None
-		})
-		.collect()
-}
deletedcrates/evm-coder/procedural/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/lib.rs
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![allow(dead_code)]
-
-use inflector::cases;
-use proc_macro::TokenStream;
-use quote::quote;
-use sha3::{Digest, Keccak256};
-use syn::{
-	DeriveInput, GenericArgument, Ident, ItemImpl, Pat, Path, PathArguments, PathSegment, Type,
-	parse_macro_input, spanned::Spanned,
-};
-
-mod abi_derive;
-mod solidity_interface;
-mod to_log;
-
-fn fn_selector_str(input: &str) -> u32 {
-	let mut hasher = Keccak256::new();
-	hasher.update(input.as_bytes());
-	let result = hasher.finalize();
-
-	let mut selector_bytes = [0; 4];
-	selector_bytes.copy_from_slice(&result[0..4]);
-
-	u32::from_be_bytes(selector_bytes)
-}
-
-/// Returns solidity function selector (first 4 bytes of hash) by its
-/// textual representation
-///
-/// ```ignore
-/// use evm_coder_macros::fn_selector;
-///
-/// assert_eq!(fn_selector!(transfer(address, uint256)), 0xa9059cbb);
-/// ```
-#[proc_macro]
-pub fn fn_selector(input: TokenStream) -> TokenStream {
-	let input = input.to_string().replace(' ', "");
-	let selector = fn_selector_str(&input);
-
-	(quote! {
-		#selector
-	})
-	.into()
-}
-
-fn event_selector_str(input: &str) -> [u8; 32] {
-	let mut hasher = Keccak256::new();
-	hasher.update(input.as_bytes());
-	let result = hasher.finalize();
-
-	let mut selector_bytes = [0; 32];
-	selector_bytes.copy_from_slice(&result[0..32]);
-	selector_bytes
-}
-
-/// Returns solidity topic (hash) by its textual representation
-///
-/// ```ignore
-/// use evm_coder_macros::event_topic;
-///
-/// assert_eq!(
-///     format!("{:x}", event_topic!(Transfer(address, address, uint256))),
-///     "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
-/// );
-/// ```
-#[proc_macro]
-pub fn event_topic(stream: TokenStream) -> TokenStream {
-	let input = stream.to_string().replace(' ', "");
-	let selector_bytes = event_selector_str(&input);
-
-	(quote! {
-		::primitive_types::H256([#(
-			#selector_bytes,
-		)*])
-	})
-	.into()
-}
-
-fn parse_path(ty: &Type) -> syn::Result<&Path> {
-	match &ty {
-		syn::Type::Path(pat) => {
-			if let Some(qself) = &pat.qself {
-				return Err(syn::Error::new(qself.ty.span(), "no receiver expected"));
-			}
-			Ok(&pat.path)
-		}
-		_ => Err(syn::Error::new(ty.span(), "expected ty to be path")),
-	}
-}
-
-fn parse_path_segment(path: &Path) -> syn::Result<&PathSegment> {
-	if path.segments.len() != 1 {
-		return Err(syn::Error::new(
-			path.span(),
-			"expected path to have only one segment",
-		));
-	}
-	let last_segment = &path.segments.last().unwrap();
-	Ok(last_segment)
-}
-
-fn parse_ident_from_pat(pat: &Pat) -> syn::Result<&Ident> {
-	match pat {
-		Pat::Ident(i) => Ok(&i.ident),
-		_ => Err(syn::Error::new(pat.span(), "expected pat ident")),
-	}
-}
-
-fn parse_ident_from_segment(segment: &PathSegment, allow_generics: bool) -> syn::Result<&Ident> {
-	if segment.arguments != PathArguments::None && !allow_generics {
-		return Err(syn::Error::new(
-			segment.arguments.span(),
-			"unexpected generic type",
-		));
-	}
-	Ok(&segment.ident)
-}
-
-fn parse_ident_from_path(path: &Path, allow_generics: bool) -> syn::Result<&Ident> {
-	let segment = parse_path_segment(path)?;
-	parse_ident_from_segment(segment, allow_generics)
-}
-
-fn parse_ident_from_type(ty: &Type, allow_generics: bool) -> syn::Result<&Ident> {
-	let path = parse_path(ty)?;
-	parse_ident_from_path(path, allow_generics)
-}
-
-// Gets T out of Result<T>
-fn parse_result_ok(ty: &Type) -> syn::Result<&Type> {
-	let path = parse_path(ty)?;
-	let segment = parse_path_segment(path)?;
-
-	if segment.ident != "Result" {
-		return Err(syn::Error::new(
-			ty.span(),
-			"expected Result as return type (no renamed aliases allowed)",
-		));
-	}
-	let args = match &segment.arguments {
-		PathArguments::AngleBracketed(e) => e,
-		_ => {
-			return Err(syn::Error::new(
-				segment.arguments.span(),
-				"missing Result generics",
-			))
-		}
-	};
-
-	let args = &args.args;
-	let arg = args.first().unwrap();
-
-	let ty = match arg {
-		GenericArgument::Type(ty) => ty,
-		_ => {
-			return Err(syn::Error::new(
-				arg.span(),
-				"expected first generic to be type",
-			))
-		}
-	};
-
-	Ok(ty)
-}
-
-fn pascal_ident_to_call(ident: &Ident) -> Ident {
-	let name = format!("{}Call", ident);
-	Ident::new(&name, ident.span())
-}
-fn snake_ident_to_pascal(ident: &Ident) -> Ident {
-	let name = ident.to_string();
-	let name = cases::pascalcase::to_pascal_case(&name);
-	Ident::new(&name, ident.span())
-}
-fn snake_ident_to_screaming(ident: &Ident) -> Ident {
-	let name = ident.to_string();
-	let name = cases::screamingsnakecase::to_screaming_snake_case(&name);
-	Ident::new(&name, ident.span())
-}
-fn pascal_ident_to_snake_call(ident: &Ident) -> Ident {
-	let name = ident.to_string();
-	let name = cases::snakecase::to_snake_case(&name);
-	let name = format!("call_{}", name);
-	Ident::new(&name, ident.span())
-}
-
-/// See documentation for this proc-macro reexported in `evm-coder` crate
-#[proc_macro_attribute]
-pub fn solidity_interface(args: TokenStream, stream: TokenStream) -> TokenStream {
-	let args = parse_macro_input!(args as solidity_interface::InterfaceInfo);
-
-	let input: ItemImpl = match syn::parse(stream) {
-		Ok(t) => t,
-		Err(e) => return e.to_compile_error().into(),
-	};
-
-	let expanded = match solidity_interface::SolidityInterface::try_from(args, &input) {
-		Ok(v) => v.expand(),
-		Err(e) => e.to_compile_error(),
-	};
-
-	(quote! {
-		#input
-
-		#expanded
-	})
-	.into()
-}
-
-#[proc_macro_attribute]
-pub fn solidity(_args: TokenStream, stream: TokenStream) -> TokenStream {
-	stream
-}
-#[proc_macro_attribute]
-pub fn weight(_args: TokenStream, stream: TokenStream) -> TokenStream {
-	stream
-}
-
-/// See documentation for this proc-macro reexported in `evm-coder` crate
-#[proc_macro_derive(ToLog, attributes(indexed))]
-pub fn to_log(value: TokenStream) -> TokenStream {
-	let input = parse_macro_input!(value as DeriveInput);
-
-	match to_log::Events::try_from(&input) {
-		Ok(e) => e.expand(),
-		Err(e) => e.to_compile_error(),
-	}
-	.into()
-}
-
-#[proc_macro_derive(AbiCoder)]
-pub fn abi_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
-	let ast = syn::parse(input).unwrap();
-	let ts = match abi_derive::impl_abi_macro(&ast) {
-		Ok(e) => e,
-		Err(e) => e.to_compile_error(),
-	};
-	ts.into()
-}
deletedcrates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/solidity_interface.rs
+++ /dev/null
@@ -1,1099 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![allow(dead_code)]
-
-// NOTE: In order to understand this Rust macro better, first read this chapter
-// about Procedural Macros in Rust book:
-// https://doc.rust-lang.org/reference/procedural-macros.html
-
-use proc_macro2::TokenStream;
-use quote::{quote, format_ident};
-use inflector::cases;
-use syn::{
-	Expr, FnArg, Generics, Ident, ImplItem, ImplItemMethod, ItemImpl, Lit, Meta, MetaNameValue,
-	PatType, ReturnType, Type,
-	spanned::Spanned,
-	parse::{Parse, ParseStream},
-	parenthesized, Token, LitInt, LitStr,
-};
-
-use crate::{
-	parse_ident_from_pat, parse_ident_from_path, parse_path, parse_path_segment, parse_result_ok,
-	pascal_ident_to_call, pascal_ident_to_snake_call, snake_ident_to_pascal,
-	snake_ident_to_screaming,
-};
-
-struct Is {
-	name: Ident,
-	pascal_call_name: Ident,
-	snake_call_name: Ident,
-	via: Option<(Type, Ident)>,
-	condition: Option<Expr>,
-}
-impl Is {
-	fn expand_call_def(&self, gen_ref: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
-		let name = &self.name;
-		let pascal_call_name = &self.pascal_call_name;
-		quote! {
-			#name(#pascal_call_name #gen_ref)
-		}
-	}
-
-	fn expand_interface_id(&self) -> proc_macro2::TokenStream {
-		let pascal_call_name = &self.pascal_call_name;
-		quote! {
-			interface_id ^= u32::from_be_bytes(#pascal_call_name::interface_id());
-		}
-	}
-
-	fn expand_supports_interface(
-		&self,
-		generics: &proc_macro2::TokenStream,
-	) -> proc_macro2::TokenStream {
-		let pascal_call_name = &self.pascal_call_name;
-		let condition = self.condition.as_ref().map(|condition| {
-			quote! {
-				(#condition) &&
-			}
-		});
-		quote! {
-			#condition <#pascal_call_name #generics>::supports_interface(this, interface_id)
-		}
-	}
-
-	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
-		let name = &self.name;
-		quote! {
-			Self::#name(call) => call.weight()
-		}
-	}
-
-	fn expand_variant_call(
-		&self,
-		call_name: &proc_macro2::Ident,
-		generics: &proc_macro2::TokenStream,
-	) -> proc_macro2::TokenStream {
-		let name = &self.name;
-		let pascal_call_name = &self.pascal_call_name;
-		let via_typ = self
-			.via
-			.as_ref()
-			.map(|(t, _)| quote! {#t})
-			.unwrap_or_else(|| quote! {Self});
-		let via_map = self
-			.via
-			.as_ref()
-			.map(|(_, i)| quote! {.#i()})
-			.unwrap_or_default();
-		let condition = self.condition.as_ref().map(|condition| {
-			quote! {
-				if ({let this = &self; (#condition)})
-			}
-		});
-		quote! {
-			#call_name::#name(call) #condition => return <#via_typ as ::evm_coder::Callable<#pascal_call_name #generics>>::call(self #via_map, Msg {
-				call,
-				caller: c.caller,
-				value: c.value,
-			})
-		}
-	}
-
-	fn expand_parse(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
-		let name = &self.name;
-		let pascal_call_name = &self.pascal_call_name;
-		quote! {
-			if let Some(parsed_call) = <#pascal_call_name #generics>::parse(method_id, reader)? {
-				return Ok(Some(Self::#name(parsed_call)))
-			}
-		}
-	}
-
-	fn expand_generator(&self, generics: &proc_macro2::TokenStream) -> proc_macro2::TokenStream {
-		let pascal_call_name = &self.pascal_call_name;
-		quote! {
-			<#pascal_call_name #generics>::generate_solidity_interface(tc, is_impl);
-		}
-	}
-
-	fn expand_event_generator(&self) -> proc_macro2::TokenStream {
-		let name = &self.name;
-		quote! {
-			#name::generate_solidity_interface(tc, is_impl);
-		}
-	}
-}
-
-#[derive(Default)]
-struct IsList(Vec<Is>);
-impl Parse for IsList {
-	fn parse(input: ParseStream) -> syn::Result<Self> {
-		let mut out = vec![];
-		loop {
-			if input.is_empty() {
-				break;
-			}
-			let name = input.parse::<Ident>()?;
-			let lookahead = input.lookahead1();
-
-			let mut condition: Option<Expr> = None;
-			let mut via: Option<(Type, Ident)> = None;
-
-			if lookahead.peek(syn::token::Paren) {
-				let contents;
-				parenthesized!(contents in input);
-				let input = contents;
-
-				while !input.is_empty() {
-					let lookahead = input.lookahead1();
-					if lookahead.peek(Token![if]) {
-						input.parse::<Token![if]>()?;
-						let contents;
-						parenthesized!(contents in input);
-						let contents = contents.parse::<Expr>()?;
-
-						if condition.replace(contents).is_some() {
-							return Err(syn::Error::new(input.span(), "condition is already set"));
-						}
-					} else if lookahead.peek(kw::via) {
-						input.parse::<kw::via>()?;
-						let contents;
-						parenthesized!(contents in input);
-
-						let method = contents.parse::<Ident>()?;
-						contents.parse::<kw::returns>()?;
-						let ty = contents.parse::<Type>()?;
-
-						if via.replace((ty, method)).is_some() {
-							return Err(syn::Error::new(input.span(), "via is already set"));
-						}
-					} else {
-						return Err(lookahead.error());
-					}
-
-					if input.peek(Token![,]) {
-						input.parse::<Token![,]>()?;
-					} else if !input.is_empty() {
-						return Err(syn::Error::new(input.span(), "expected end"));
-					}
-				}
-			} else if lookahead.peek(Token![,]) || input.is_empty() {
-				// Pass
-			} else {
-				return Err(lookahead.error());
-			};
-			out.push(Is {
-				pascal_call_name: pascal_ident_to_call(&name),
-				snake_call_name: pascal_ident_to_snake_call(&name),
-				name,
-				via,
-				condition,
-			});
-			if input.peek(Token![,]) {
-				input.parse::<Token![,]>()?;
-				continue;
-			} else {
-				break;
-			}
-		}
-		Ok(Self(out))
-	}
-}
-
-pub struct InterfaceInfo {
-	name: Ident,
-	is: IsList,
-	inline_is: IsList,
-	events: IsList,
-	expect_selector: Option<u32>,
-}
-impl Parse for InterfaceInfo {
-	fn parse(input: ParseStream) -> syn::Result<Self> {
-		let mut name = None;
-		let mut is = None;
-		let mut inline_is = None;
-		let mut events = None;
-		let mut expect_selector = None;
-		// TODO: create proc-macro to optimize proc-macro boilerplate? :D
-		loop {
-			let lookahead = input.lookahead1();
-			if lookahead.peek(kw::name) {
-				let k = input.parse::<kw::name>()?;
-				input.parse::<Token![=]>()?;
-				if name.replace(input.parse::<Ident>()?).is_some() {
-					return Err(syn::Error::new(k.span(), "name is already set"));
-				}
-			} else if lookahead.peek(kw::is) {
-				let k = input.parse::<kw::is>()?;
-				let contents;
-				parenthesized!(contents in input);
-				if is.replace(contents.parse::<IsList>()?).is_some() {
-					return Err(syn::Error::new(k.span(), "is is already set"));
-				}
-			} else if lookahead.peek(kw::inline_is) {
-				let k = input.parse::<kw::inline_is>()?;
-				let contents;
-				parenthesized!(contents in input);
-				if inline_is.replace(contents.parse::<IsList>()?).is_some() {
-					return Err(syn::Error::new(k.span(), "inline_is is already set"));
-				}
-			} else if lookahead.peek(kw::events) {
-				let k = input.parse::<kw::events>()?;
-				let contents;
-				parenthesized!(contents in input);
-				if events.replace(contents.parse::<IsList>()?).is_some() {
-					return Err(syn::Error::new(k.span(), "events is already set"));
-				}
-			} else if lookahead.peek(kw::expect_selector) {
-				let k = input.parse::<kw::expect_selector>()?;
-				input.parse::<Token![=]>()?;
-				let value = input.parse::<LitInt>()?;
-				if expect_selector
-					.replace(value.base10_parse::<u32>()?)
-					.is_some()
-				{
-					return Err(syn::Error::new(k.span(), "expect_selector is already set"));
-				}
-			} else if input.is_empty() {
-				break;
-			} else {
-				return Err(lookahead.error());
-			}
-			if input.peek(Token![,]) {
-				input.parse::<Token![,]>()?;
-			} else {
-				break;
-			}
-		}
-		Ok(Self {
-			name: name.ok_or_else(|| syn::Error::new(input.span(), "missing name"))?,
-			is: is.unwrap_or_default(),
-			inline_is: inline_is.unwrap_or_default(),
-			events: events.unwrap_or_default(),
-			expect_selector,
-		})
-	}
-}
-
-struct MethodInfo {
-	rename_selector: Option<String>,
-	hide: bool,
-}
-impl Parse for MethodInfo {
-	fn parse(input: ParseStream) -> syn::Result<Self> {
-		let mut rename_selector = None;
-		let mut hide = false;
-		while !input.is_empty() {
-			let lookahead = input.lookahead1();
-			if lookahead.peek(kw::rename_selector) {
-				let k = input.parse::<kw::rename_selector>()?;
-				input.parse::<Token![=]>()?;
-				if rename_selector
-					.replace(input.parse::<LitStr>()?.value())
-					.is_some()
-				{
-					return Err(syn::Error::new(k.span(), "rename_selector is already set"));
-				}
-			} else if lookahead.peek(kw::hide) {
-				input.parse::<kw::hide>()?;
-				hide = true;
-			} else {
-				return Err(lookahead.error());
-			}
-
-			if input.peek(Token![,]) {
-				input.parse::<Token![,]>()?;
-			} else if !input.is_empty() {
-				return Err(syn::Error::new(input.span(), "expected end"));
-			}
-		}
-		Ok(Self {
-			rename_selector,
-			hide,
-		})
-	}
-}
-
-trait AbiTypeHelper {
-	fn plain(&self) -> syn::Result<&Ident>;
-	fn is_value(&self) -> bool;
-	fn is_caller(&self) -> bool;
-	fn is_special(&self) -> bool;
-}
-
-impl AbiTypeHelper for Type {
-	fn plain(&self) -> syn::Result<&Ident> {
-		let path = parse_path(self)?;
-		let segment = parse_path_segment(path)?;
-		if !segment.arguments.is_empty() {
-			return Err(syn::Error::new(self.span(), "Not plain type"));
-		}
-		Ok(&segment.ident)
-	}
-
-	fn is_value(&self) -> bool {
-		if let Ok(ident) = self.plain() {
-			return ident == "Value";
-		}
-		false
-	}
-
-	fn is_caller(&self) -> bool {
-		if let Ok(ident) = self.plain() {
-			return ident == "Caller";
-		}
-		false
-	}
-
-	fn is_special(&self) -> bool {
-		self.is_caller() || self.is_value()
-	}
-}
-
-#[derive(Debug)]
-struct MethodArg {
-	name: Ident,
-	camel_name: String,
-	ty: Type,
-}
-impl MethodArg {
-	fn try_from(value: &PatType) -> syn::Result<Self> {
-		let name = parse_ident_from_pat(&value.pat)?.clone();
-		Ok(Self {
-			camel_name: cases::camelcase::to_camel_case(&name.to_string()),
-			name,
-			ty: value.ty.as_ref().clone(),
-		})
-	}
-	fn is_value(&self) -> bool {
-		self.ty.is_value()
-	}
-	fn is_caller(&self) -> bool {
-		self.ty.is_caller()
-	}
-	fn is_special(&self) -> bool {
-		self.ty.is_special()
-	}
-
-	fn expand_call_def(&self) -> proc_macro2::TokenStream {
-		assert!(!self.is_special());
-		let name = &self.name;
-		let ty = &self.ty;
-
-		quote! {
-			#name: #ty
-		}
-	}
-
-	fn expand_parse(&self) -> proc_macro2::TokenStream {
-		assert!(!self.is_special());
-		let name = &self.name;
-		let ty = &self.ty;
-		quote! {
-			#name: {
-				let value = <#ty as ::evm_coder::abi::AbiRead>::abi_read(reader)?;
-				if !is_dynamic {reader.bytes_read(<#ty as ::evm_coder::abi::AbiType>::size())};
-				value
-			}
-		}
-	}
-
-	fn expand_call_arg(&self) -> proc_macro2::TokenStream {
-		if self.is_value() {
-			quote! {
-				c.value.clone()
-			}
-		} else if self.is_caller() {
-			quote! {
-				c.caller.clone()
-			}
-		} else {
-			let name = &self.name;
-			quote! {
-				#name
-			}
-		}
-	}
-
-	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
-		let camel_name = &self.camel_name.to_string();
-		let ty = &self.ty;
-		quote! {
-			<NamedArgument<#ty>>::new(#camel_name)
-		}
-	}
-}
-
-#[derive(PartialEq)]
-enum Mutability {
-	Mutable,
-	View,
-	Pure,
-}
-
-/// Group all keywords for this macro. Usage example:
-/// #[solidity_interface(name = "B", inline_is(A))]
-mod kw {
-	syn::custom_keyword!(weight);
-
-	syn::custom_keyword!(via);
-	syn::custom_keyword!(returns);
-	syn::custom_keyword!(name);
-	syn::custom_keyword!(is);
-	syn::custom_keyword!(inline_is);
-	syn::custom_keyword!(events);
-	syn::custom_keyword!(expect_selector);
-
-	syn::custom_keyword!(rename_selector);
-	syn::custom_keyword!(hide);
-}
-
-/// Rust methods are parsed into this structure when Solidity code is generated
-struct Method {
-	name: Ident,
-	camel_name: String,
-	pascal_name: Ident,
-	screaming_name: Ident,
-	hide: bool,
-	args: Vec<MethodArg>,
-	has_normal_args: bool,
-	has_value_args: bool,
-	mutability: Mutability,
-	result: Type,
-	weight: Option<Expr>,
-	docs: Vec<String>,
-}
-impl Method {
-	fn try_from(value: &ImplItemMethod) -> syn::Result<Self> {
-		let mut info = MethodInfo {
-			rename_selector: None,
-			hide: false,
-		};
-		let mut docs = Vec::new();
-		let mut weight = None;
-		for attr in &value.attrs {
-			let ident = parse_ident_from_path(&attr.path, false)?;
-			if ident == "solidity" {
-				info = attr.parse_args::<MethodInfo>()?;
-			} else if ident == "doc" {
-				let args = attr.parse_meta().unwrap();
-				let value = match args {
-					Meta::NameValue(MetaNameValue {
-						lit: Lit::Str(str), ..
-					}) => str.value(),
-					_ => unreachable!(),
-				};
-				docs.push(value);
-			} else if ident == "weight" {
-				weight = Some(attr.parse_args::<Expr>()?);
-			}
-		}
-		let ident = &value.sig.ident;
-		let ident_str = ident.to_string();
-		if !cases::snakecase::is_snake_case(&ident_str) {
-			return Err(syn::Error::new(ident.span(), "method name should be snake_cased\nif alternative solidity name needs to be set - use #[solidity] attribute"));
-		}
-
-		let mut mutability = Mutability::Pure;
-
-		if let Some(FnArg::Receiver(receiver)) = value
-			.sig
-			.inputs
-			.iter()
-			.find(|arg| matches!(arg, FnArg::Receiver(_)))
-		{
-			if receiver.reference.is_none() {
-				return Err(syn::Error::new(
-					receiver.span(),
-					"receiver should be by ref",
-				));
-			}
-			if receiver.mutability.is_some() {
-				mutability = Mutability::Mutable;
-			} else {
-				mutability = Mutability::View;
-			}
-		}
-		let mut args = Vec::new();
-		for typ in value
-			.sig
-			.inputs
-			.iter()
-			.filter(|arg| matches!(arg, FnArg::Typed(_)))
-		{
-			let typ = match typ {
-				FnArg::Typed(typ) => typ,
-				_ => unreachable!(),
-			};
-			args.push(MethodArg::try_from(typ)?);
-		}
-
-		if mutability != Mutability::Mutable && args.iter().any(|arg| arg.is_value()) {
-			return Err(syn::Error::new(
-				args.iter().find(|arg| arg.is_value()).unwrap().ty.span(),
-				"payable function should be mutable",
-			));
-		}
-
-		let result = match &value.sig.output {
-			ReturnType::Type(_, ty) => ty,
-			_ => return Err(syn::Error::new(value.sig.output.span(), "interface method should return Result<value>\nif there is no value to return - specify void (which is alias to unit)")),
-		};
-		let result = parse_result_ok(result)?;
-
-		let camel_name = info
-			.rename_selector
-			.unwrap_or_else(|| cases::camelcase::to_camel_case(&ident.to_string()));
-		let has_normal_args = args.iter().filter(|arg| !arg.is_special()).count() != 0;
-		let has_value_args = args.iter().any(|a| a.is_value());
-
-		Ok(Self {
-			name: ident.clone(),
-			camel_name,
-			pascal_name: snake_ident_to_pascal(ident),
-			screaming_name: snake_ident_to_screaming(ident),
-			hide: info.hide,
-			args,
-			has_normal_args,
-			has_value_args,
-			mutability,
-			result: result.clone(),
-			weight,
-			docs,
-		})
-	}
-	fn expand_call_def(&self) -> proc_macro2::TokenStream {
-		let defs = self
-			.args
-			.iter()
-			.filter(|a| !a.is_special())
-			.map(|a| a.expand_call_def());
-		let pascal_name = &self.pascal_name;
-		let docs = &self.docs;
-
-		if self.has_normal_args {
-			quote! {
-				#(#[doc = #docs])*
-				#[allow(missing_docs)]
-				#pascal_name {
-					#(
-						#defs,
-					)*
-				}
-			}
-		} else {
-			quote! {
-				#(#[doc = #docs])*
-				#[allow(missing_docs)]
-				#pascal_name
-			}
-		}
-	}
-
-	fn expand_const(&self) -> proc_macro2::TokenStream {
-		let screaming_name = &self.screaming_name;
-		let screaming_name_signature = format_ident!("{}_SIGNATURE", &self.screaming_name);
-		let custom_signature = self.expand_custom_signature();
-		quote! {
-			const #screaming_name_signature: ::evm_coder::custom_signature::SignatureUnit = #custom_signature;
-			const #screaming_name: ::evm_coder::types::Bytes4 = {
-				let mut sum = ::evm_coder::sha3_const::Keccak256::new();
-				let mut pos = 0;
-				while pos < Self::#screaming_name_signature.len {
-					sum = sum.update(&[Self::#screaming_name_signature.data[pos]; 1]);
-					pos += 1;
-				}
-				let a = sum.finalize();
-				[a[0], a[1], a[2], a[3]]
-			};
-		}
-	}
-
-	fn expand_interface_id(&self) -> proc_macro2::TokenStream {
-		let screaming_name = &self.screaming_name;
-		quote! {
-			interface_id ^= u32::from_be_bytes(Self::#screaming_name);
-		}
-	}
-
-	fn expand_parse(&self) -> proc_macro2::TokenStream {
-		let pascal_name = &self.pascal_name;
-		let screaming_name = &self.screaming_name;
-		if self.has_normal_args {
-			let args_iter = self.args.iter().filter(|a| !a.is_special());
-			let arg_type = args_iter.clone().map(|a| &a.ty);
-			let parsers = args_iter.map(|a| a.expand_parse());
-			quote! {
-				Self::#screaming_name => {
-					let is_dynamic = false #(|| <#arg_type as ::evm_coder::abi::AbiType>::is_dynamic())*;
-					return Ok(Some(Self::#pascal_name {
-						#(
-							#parsers,
-						)*
-					}))
-				}
-			}
-		} else {
-			quote! { Self::#screaming_name => return Ok(Some(Self::#pascal_name)) }
-		}
-	}
-
-	fn expand_variant_call(&self, call_name: &proc_macro2::Ident) -> proc_macro2::TokenStream {
-		let pascal_name = &self.pascal_name;
-		let name = &self.name;
-
-		let matcher = if self.has_normal_args {
-			let names = self
-				.args
-				.iter()
-				.filter(|a| !a.is_special())
-				.map(|a| &a.name);
-
-			quote! {{
-				#(
-					#names,
-				)*
-			}}
-		} else {
-			quote! {}
-		};
-
-		let receiver = match self.mutability {
-			Mutability::Mutable | Mutability::View => quote! {self.},
-			Mutability::Pure => quote! {Self::},
-		};
-		let args = self.args.iter().map(|a| a.expand_call_arg());
-
-		quote! {
-			#call_name::#pascal_name #matcher => {
-				#[allow(deprecated)]
-				let result = #receiver #name(
-					#(
-						#args,
-					)*
-				)?;
-				(&result).to_result()
-			}
-		}
-	}
-
-	fn expand_variant_weight(&self) -> proc_macro2::TokenStream {
-		let pascal_name = &self.pascal_name;
-		if let Some(weight) = &self.weight {
-			let matcher = if self.has_normal_args {
-				let names = self
-					.args
-					.iter()
-					.filter(|a| !a.is_special())
-					.map(|a| &a.name);
-
-				quote! {{
-					#(
-						#names,
-					)*
-				}}
-			} else {
-				quote! {}
-			};
-			quote! {
-				Self::#pascal_name #matcher => (#weight).into()
-			}
-		} else {
-			let matcher = if self.has_normal_args {
-				quote! {{..}}
-			} else {
-				quote! {}
-			};
-			quote! {
-				Self::#pascal_name #matcher => ().into()
-			}
-		}
-	}
-
-	fn expand_custom_signature(&self) -> proc_macro2::TokenStream {
-		let mut args = TokenStream::new();
-
-		let mut has_params = false;
-		for arg in self.args.iter().filter(|a| !a.is_special()) {
-			has_params = true;
-			let ty = &arg.ty;
-			args.extend(quote! {nameof(<#ty>::SIGNATURE)});
-			args.extend(quote! {fixed(",")})
-		}
-
-		// Remove trailing comma
-		if has_params {
-			args.extend(quote! {shift_left(1)})
-		}
-
-		let func_name = self.camel_name.clone();
-		quote! { ::evm_coder::make_signature!(new fixed(#func_name) fixed("(") #args fixed(")")) }
-	}
-
-	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
-		let camel_name = &self.camel_name;
-		let mutability = match self.mutability {
-			Mutability::Mutable => quote! {SolidityMutability::Mutable},
-			Mutability::View => quote! { SolidityMutability::View },
-			Mutability::Pure => quote! {SolidityMutability::Pure},
-		};
-		let result = &self.result;
-
-		let args = self
-			.args
-			.iter()
-			.filter(|a| !a.is_special())
-			.map(MethodArg::expand_solidity_argument);
-		let docs = &self.docs;
-		let screaming_name = &self.screaming_name;
-		let hide = self.hide;
-		let custom_signature = self.expand_custom_signature();
-		let is_payable = self.has_value_args;
-
-		quote! {
-			SolidityFunction {
-				docs: &[#(#docs),*],
-				hide: #hide,
-				selector: u32::from_be_bytes(Self::#screaming_name),
-				custom_signature: #custom_signature,
-				name: #camel_name,
-				mutability: #mutability,
-				is_payable: #is_payable,
-				args: (
-					#(
-						#args,
-					)*
-				),
-				result: <UnnamedArgument<#result>>::default(),
-			}
-		}
-	}
-}
-
-fn generics_list(gen: &Generics) -> proc_macro2::TokenStream {
-	if gen.params.is_empty() {
-		return quote! {};
-	}
-	let params = gen.params.iter().map(|p| match p {
-		syn::GenericParam::Type(id) => {
-			let v = &id.ident;
-			quote! {#v}
-		}
-		syn::GenericParam::Lifetime(lt) => {
-			let v = &lt.lifetime;
-			quote! {#v}
-		}
-		syn::GenericParam::Const(c) => {
-			let i = &c.ident;
-			quote! {#i}
-		}
-	});
-	quote! { #(#params),* }
-}
-fn generics_reference(gen: &Generics) -> proc_macro2::TokenStream {
-	if gen.params.is_empty() {
-		return quote! {};
-	}
-	let list = generics_list(gen);
-	quote! { <#list> }
-}
-fn generics_stub(gen: &Generics) -> proc_macro2::TokenStream {
-	if gen.params.is_empty() {
-		return quote! {};
-	}
-	let params = (0..gen.params.len()).map(|_| quote! {()});
-	quote! {<#(#params,)*>}
-}
-fn generics_data(gen: &Generics) -> proc_macro2::TokenStream {
-	let list = generics_list(gen);
-	if gen.params.len() == 1 {
-		quote! {#list}
-	} else {
-		quote! { (#list) }
-	}
-}
-
-pub struct SolidityInterface {
-	generics: Generics,
-	name: Box<syn::Type>,
-	info: InterfaceInfo,
-	methods: Vec<Method>,
-	docs: Vec<String>,
-}
-impl SolidityInterface {
-	pub fn try_from(info: InterfaceInfo, value: &ItemImpl) -> syn::Result<Self> {
-		let mut methods = Vec::new();
-
-		for item in &value.items {
-			if let ImplItem::Method(method) = item {
-				methods.push(Method::try_from(method)?)
-			}
-		}
-		let mut docs = vec![];
-		for attr in &value.attrs {
-			let ident = parse_ident_from_path(&attr.path, false)?;
-			if ident == "doc" {
-				let args = attr.parse_meta().unwrap();
-				let value = match args {
-					Meta::NameValue(MetaNameValue {
-						lit: Lit::Str(str), ..
-					}) => str.value(),
-					_ => unreachable!(),
-				};
-				docs.push(value);
-			}
-		}
-		Ok(Self {
-			generics: value.generics.clone(),
-			name: value.self_ty.clone(),
-			info,
-			methods,
-			docs,
-		})
-	}
-	pub fn expand(self) -> proc_macro2::TokenStream {
-		let name = self.name;
-
-		let solidity_name = self.info.name.to_string();
-		let call_name = pascal_ident_to_call(&self.info.name);
-		let generics = self.generics;
-		let gen_ref = generics_reference(&generics);
-		let gen_data = generics_data(&generics);
-		let gen_stub = generics_stub(&generics);
-		let gen_where = &generics.where_clause;
-
-		let call_sub = self
-			.info
-			.inline_is
-			.0
-			.iter()
-			.chain(self.info.is.0.iter())
-			.map(|c| Is::expand_call_def(c, &gen_ref));
-		let call_parse = self
-			.info
-			.inline_is
-			.0
-			.iter()
-			.chain(self.info.is.0.iter())
-			.map(|is| Is::expand_parse(is, &gen_ref));
-		let call_variants = self
-			.info
-			.inline_is
-			.0
-			.iter()
-			.chain(self.info.is.0.iter())
-			.map(|c| Is::expand_variant_call(c, &call_name, &gen_ref));
-		let weight_variants = self
-			.info
-			.inline_is
-			.0
-			.iter()
-			.chain(self.info.is.0.iter())
-			.map(Is::expand_variant_weight);
-
-		let inline_interface_id = self.info.inline_is.0.iter().map(Is::expand_interface_id);
-		let supports_interface = self
-			.info
-			.is
-			.0
-			.iter()
-			.map(|is| Is::expand_supports_interface(is, &gen_ref));
-
-		let calls = self.methods.iter().map(Method::expand_call_def);
-		let consts = self.methods.iter().map(Method::expand_const);
-		let interface_id = self.methods.iter().map(Method::expand_interface_id);
-		let parsers = self.methods.iter().map(Method::expand_parse);
-		let call_variants_this = self
-			.methods
-			.iter()
-			.map(|m| Method::expand_variant_call(m, &call_name));
-		let weight_variants_this = self.methods.iter().map(Method::expand_variant_weight);
-		let solidity_functions = self.methods.iter().map(Method::expand_solidity_function);
-
-		// TODO: Inline inline_is
-		let solidity_is = self
-			.info
-			.is
-			.0
-			.iter()
-			.chain(self.info.inline_is.0.iter())
-			.map(|is| is.name.to_string());
-		let solidity_events_is = self.info.events.0.iter().map(|is| is.name.to_string());
-		let solidity_generators = self
-			.info
-			.is
-			.0
-			.iter()
-			.chain(self.info.inline_is.0.iter())
-			.map(|is| Is::expand_generator(is, &gen_ref));
-		let solidity_event_generators = self.info.events.0.iter().map(Is::expand_event_generator);
-		let solidity_events_idents = self.info.events.0.iter().map(|is| is.name.clone());
-		let docs = &self.docs;
-
-		let expect_selector = self.info.expect_selector.map(|s| {
-            quote! {
-                const _: () = assert!(#s == u32::from_be_bytes(<#call_name #gen_stub>::interface_id()), "selector mismatch, review contained function selectors");
-            }
-        });
-
-		quote! {
-			#(
-				const _: ::core::marker::PhantomData<#solidity_events_idents> = ::core::marker::PhantomData;
-			)*
-			#[derive(Debug)]
-			#(#[doc = #docs])*
-			pub enum #call_name #gen_ref {
-				/// Inherited method
-				ERC165Call(::evm_coder::ERC165Call, ::core::marker::PhantomData<#gen_data>),
-				#(
-					#calls,
-				)*
-				#(
-					#call_sub,
-				)*
-			}
-
-			#expect_selector
-
-			impl #gen_ref #call_name #gen_ref {
-				#(
-					#consts
-				)*
-				/// Return this call ERC165 selector
-				pub const fn interface_id() -> ::evm_coder::types::Bytes4 {
-					let mut interface_id = 0;
-					#(#interface_id)*
-					#(#inline_interface_id)*
-					u32::to_be_bytes(interface_id)
-				}
-				/// Generate solidity definitions for methods described in this interface
-				#[cfg(feature = "stubgen")]
-				pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
-					use evm_coder::solidity::*;
-					use core::fmt::Write;
-					let interface = SolidityInterface {
-						docs: &[#(#docs),*],
-						name: #solidity_name,
-						selector: Self::interface_id(),
-						is: &["Dummy", "ERC165", #(
-							#solidity_is,
-						)* #(
-							#solidity_events_is,
-						)* ],
-						functions: (#(
-							#solidity_functions,
-						)*),
-					};
-
-					let mut out = ::evm_coder::types::String::new();
-					if #solidity_name.starts_with("Inline") {
-						out.push_str("/// @dev inlined interface\n");
-					}
-					let _ = interface.format(is_impl, &mut out, tc);
-					tc.collect(out);
-					#(
-						#solidity_event_generators
-					)*
-					#(
-						#solidity_generators
-					)*
-					if is_impl {
-						tc.collect("/// @dev common stubs holder\ncontract Dummy {\n\tuint8 dummy;\n\tstring stub_error = \"this contract is implemented in native\";\n}\ncontract ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool) {\n\t\trequire(false, stub_error);\n\t\tinterfaceID;\n\t\treturn true;\n\t}\n}\n".into());
-					} else {
-						tc.collect("/// @dev common stubs holder\ninterface Dummy {\n}\ninterface ERC165 is Dummy {\n\tfunction supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n".into());
-					}
-				}
-			}
-			impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {
-				fn parse(method_id: ::evm_coder::types::Bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
-					use ::evm_coder::abi::AbiRead;
-					match method_id {
-						::evm_coder::ERC165Call::INTERFACE_ID => return Ok(
-							::evm_coder::ERC165Call::parse(method_id, reader)?
-							.map(|c| Self::ERC165Call(c, ::core::marker::PhantomData))
-						),
-						#(
-							#parsers,
-						)*
-						_ => {},
-					}
-					#(
-						#call_parse
-					)else*
-					return Ok(None);
-				}
-			}
-			impl #generics #call_name #gen_ref
-			#gen_where
-			{
-				/// Is this contract implements specified ERC165 selector
-				pub fn supports_interface(this: &#name, interface_id: ::evm_coder::types::Bytes4) -> bool {
-					interface_id != u32::to_be_bytes(0xffffff) && (
-						interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||
-						interface_id == Self::interface_id()
-						#(
-							|| #supports_interface
-						)*
-					)
-				}
-			}
-			impl #generics ::evm_coder::Weighted for #call_name #gen_ref
-			#gen_where
-			{
-				#[allow(unused_variables)]
-				fn weight(&self) -> ::evm_coder::execution::DispatchInfo {
-					match self {
-						#(
-							#weight_variants,
-						)*
-						// TODO: It should be very cheap, but not free
-						Self::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {..}, _) => ::frame_support::weights::Weight::from_ref_time(100).into(),
-						#(
-							#weight_variants_this,
-						)*
-					}
-				}
-			}
-			impl #generics ::evm_coder::Callable<#call_name #gen_ref> for #name
-			#gen_where
-			{
-				#[allow(unreachable_code)] // In case of no inner calls
-				fn call(&mut self, c: Msg<#call_name #gen_ref>) -> ::evm_coder::execution::ResultWithPostInfo<::evm_coder::abi::AbiWriter> {
-					use ::evm_coder::abi::AbiWrite;
-					match c.call {
-						#(
-							#call_variants,
-						)*
-						#call_name::ERC165Call(::evm_coder::ERC165Call::SupportsInterface {interface_id}, _) => {
-							let mut writer = ::evm_coder::abi::AbiWriter::default();
-							writer.bool(&<#call_name #gen_ref>::supports_interface(self, interface_id));
-							return Ok(writer.into());
-						}
-						_ => {},
-					}
-					let mut writer = ::evm_coder::abi::AbiWriter::default();
-					match c.call {
-						#(
-							#call_variants_this,
-						)*
-						_ => Err(::evm_coder::execution::Error::from("method is not available").into()),
-					}
-				}
-			}
-		}
-	}
-}
deletedcrates/evm-coder/procedural/src/to_log.rsdiffbeforeafterboth
--- a/crates/evm-coder/procedural/src/to_log.rs
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use inflector::cases;
-use syn::{Data, DeriveInput, Field, Fields, Ident, Variant, spanned::Spanned};
-use quote::quote;
-
-use crate::{parse_ident_from_path, parse_ident_from_type, snake_ident_to_screaming};
-
-struct EventField {
-	name: Ident,
-	camel_name: String,
-	ty: Ident,
-	indexed: bool,
-}
-
-impl EventField {
-	fn try_from(field: &Field) -> syn::Result<Self> {
-		let name = field.ident.as_ref().unwrap();
-		let ty = parse_ident_from_type(&field.ty, false)?;
-		let mut indexed = false;
-		for attr in &field.attrs {
-			if let Ok(ident) = parse_ident_from_path(&attr.path, false) {
-				if ident == "indexed" {
-					indexed = true;
-				}
-			}
-		}
-		Ok(Self {
-			name: name.to_owned(),
-			camel_name: cases::camelcase::to_camel_case(&name.to_string()),
-			ty: ty.to_owned(),
-			indexed,
-		})
-	}
-	fn expand_solidity_argument(&self) -> proc_macro2::TokenStream {
-		let camel_name = &self.camel_name;
-		let ty = &self.ty;
-		let indexed = self.indexed;
-		quote! {
-			<SolidityEventArgument<#ty>>::new(#indexed, #camel_name)
-		}
-	}
-}
-
-struct Event {
-	name: Ident,
-	name_screaming: Ident,
-	fields: Vec<EventField>,
-	selector: proc_macro2::TokenStream,
-}
-
-impl Event {
-	fn try_from(variant: &Variant) -> syn::Result<Self> {
-		let name = &variant.ident;
-		let name_lit = proc_macro2::Literal::string(name.to_string().as_str());
-		let name_screaming = snake_ident_to_screaming(name);
-
-		let named = match &variant.fields {
-			Fields::Named(named) => named,
-			_ => {
-				return Err(syn::Error::new(
-					variant.fields.span(),
-					"expected named fields",
-				))
-			}
-		};
-		let mut fields = Vec::new();
-		for field in &named.named {
-			fields.push(EventField::try_from(field)?);
-		}
-		if fields.iter().filter(|f| f.indexed).count() > 3 {
-			return Err(syn::Error::new(
-				variant.fields.span(),
-				"events can have at most 4 indexed fields (1 indexed field is reserved for event signature)"
-			));
-		}
-
-		let args = fields.iter().map(|f| {
-			let ty = &f.ty;
-			quote! {nameof(<#ty as ::evm_coder::abi::AbiType>::SIGNATURE) fixed(",")}
-		});
-		// Remove trailing comma
-		let shift = (!fields.is_empty()).then(|| quote! {shift_left(1)});
-
-		let signature = quote! { ::evm_coder::make_signature!(new fixed(#name_lit) fixed("(") #(#args)* #shift fixed(")")) };
-		let selector = quote! {
-			{
-				let signature = #signature;
-				let mut sum = ::evm_coder::sha3_const::Keccak256::new();
-				let mut pos = 0;
-				while pos < signature.len {
-					sum = sum.update(&[signature.data[pos]; 1]);
-					pos += 1;
-				}
-				let a = sum.finalize();
-				let mut selector_bytes = [0; 32];
-				let mut i = 0;
-				while i != 32 {
-					selector_bytes[i] = a[i];
-					i += 1;
-				}
-				selector_bytes
-			}
-		};
-
-		Ok(Self {
-			name: name.to_owned(),
-			name_screaming,
-			fields,
-			selector,
-		})
-	}
-
-	fn expand_serializers(&self) -> proc_macro2::TokenStream {
-		let name = &self.name;
-		let name_screaming = &self.name_screaming;
-		let fields = self.fields.iter().map(|f| &f.name);
-
-		let indexed = self.fields.iter().filter(|f| f.indexed).map(|f| &f.name);
-		let plain = self.fields.iter().filter(|f| !f.indexed).map(|f| &f.name);
-
-		quote! {
-			Self::#name {#(
-				#fields,
-			)*} => {
-				topics.push(::evm_coder::types::Topic::from(Self::#name_screaming));
-				#(
-					topics.push(#indexed.to_topic());
-				)*
-				#(
-					#plain.abi_write(&mut writer);
-				)*
-			}
-		}
-	}
-
-	fn expand_consts(&self) -> proc_macro2::TokenStream {
-		let name_screaming = &self.name_screaming;
-		let selector = &self.selector;
-
-		quote! {
-			const #name_screaming: [u8; 32] = #selector;
-		}
-	}
-
-	fn expand_solidity_function(&self) -> proc_macro2::TokenStream {
-		let name = self.name.to_string();
-		let args = self.fields.iter().map(EventField::expand_solidity_argument);
-		quote! {
-			SolidityEvent {
-				name: #name,
-				args: (
-					#(
-						#args,
-					)*
-				),
-			}
-		}
-	}
-}
-
-pub struct Events {
-	name: Ident,
-	events: Vec<Event>,
-}
-
-impl Events {
-	pub fn try_from(data: &DeriveInput) -> syn::Result<Self> {
-		let name = &data.ident;
-		let en = match &data.data {
-			Data::Enum(en) => en,
-			_ => return Err(syn::Error::new(data.span(), "expected enum")),
-		};
-		let mut events = Vec::new();
-		for variant in &en.variants {
-			events.push(Event::try_from(variant)?);
-		}
-		Ok(Self {
-			name: name.to_owned(),
-			events,
-		})
-	}
-	pub fn expand(&self) -> proc_macro2::TokenStream {
-		let name = &self.name;
-
-		let consts = self.events.iter().map(Event::expand_consts);
-		let serializers = self.events.iter().map(Event::expand_serializers);
-		let solidity_name = self.name.to_string();
-		let solidity_functions = self.events.iter().map(Event::expand_solidity_function);
-
-		quote! {
-			impl #name {
-				#(
-					#consts
-				)*
-
-				/// Generate solidity definitions for methods described in this interface
-				#[cfg(feature = "stubgen")]
-				pub fn generate_solidity_interface(tc: &evm_coder::solidity::TypeCollector, is_impl: bool) {
-					use evm_coder::solidity::*;
-					use core::fmt::Write;
-					let interface = SolidityInterface {
-						docs: &[],
-						selector: [0; 4],
-						name: #solidity_name,
-						is: &[],
-						functions: (#(
-							#solidity_functions,
-						)*),
-					};
-					let mut out = ::evm_coder::types::String::new();
-					out.push_str("/// @dev inlined interface\n");
-					let _ = interface.format(is_impl, &mut out, tc);
-					tc.collect(out);
-				}
-			}
-
-			#[automatically_derived]
-			impl ::evm_coder::events::ToLog for #name {
-				fn to_log(&self, contract: Address) -> ::evm_coder::ethereum::Log {
-					use ::evm_coder::events::ToTopic;
-					use ::evm_coder::abi::AbiWrite;
-					let mut writer = ::evm_coder::abi::AbiWriter::new();
-					let mut topics = Vec::new();
-					match self {
-						#(
-							#serializers,
-						)*
-					}
-					::evm_coder::ethereum::Log {
-						address: contract,
-						topics,
-						data: writer.finish(),
-					}
-				}
-			}
-		}
-	}
-}
deletedcrates/evm-coder/src/abi/impls.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi/impls.rs
+++ /dev/null
@@ -1,296 +0,0 @@
-use crate::{
-	custom_signature::SignatureUnit,
-	execution::{Result, ResultWithPostInfo, WithPostDispatchInfo},
-	make_signature, sealed,
-	types::*,
-};
-use super::{traits::*, ABI_ALIGNMENT, AbiReader, AbiWriter};
-use primitive_types::{U256, H160};
-
-#[cfg(not(feature = "std"))]
-use alloc::vec::Vec;
-
-macro_rules! impl_abi_type {
-	($ty:ty, $name:ident, $dynamic:literal) => {
-		impl sealed::CanBePlacedInVec for $ty {}
-
-		impl AbiType for $ty {
-			const SIGNATURE: SignatureUnit = make_signature!(new fixed(stringify!($name)));
-
-			fn is_dynamic() -> bool {
-				$dynamic
-			}
-
-			fn size() -> usize {
-				ABI_ALIGNMENT
-			}
-		}
-	};
-}
-
-macro_rules! impl_abi_readable {
-	($ty:ty, $method:ident) => {
-		impl AbiRead for $ty {
-			fn abi_read(reader: &mut AbiReader) -> Result<$ty> {
-				reader.$method()
-			}
-		}
-	};
-}
-
-macro_rules! impl_abi_writeable {
-	($ty:ty, $method:ident) => {
-		impl AbiWrite for $ty {
-			fn abi_write(&self, writer: &mut AbiWriter) {
-				writer.$method(&self)
-			}
-		}
-	};
-}
-
-macro_rules! impl_abi {
-	($ty:ty, $method:ident, $dynamic:literal) => {
-		impl_abi_type!($ty, $method, $dynamic);
-		impl_abi_readable!($ty, $method);
-		impl_abi_writeable!($ty, $method);
-	};
-}
-
-impl_abi!(bool, bool, false);
-impl_abi!(u8, uint8, false);
-impl_abi!(u32, uint32, false);
-impl_abi!(u64, uint64, false);
-impl_abi!(u128, uint128, false);
-impl_abi!(U256, uint256, false);
-impl_abi!(H160, address, false);
-impl_abi!(String, string, true);
-
-impl_abi_writeable!(&str, string);
-
-impl_abi_type!(Bytes, bytes, true);
-
-impl AbiRead for Bytes {
-	fn abi_read(reader: &mut AbiReader) -> Result<Bytes> {
-		Ok(Bytes(reader.bytes()?))
-	}
-}
-
-impl AbiWrite for Bytes {
-	fn abi_write(&self, writer: &mut AbiWriter) {
-		writer.bytes(self.0.as_slice())
-	}
-}
-
-impl_abi_type!(Bytes4, bytes4, false);
-impl AbiRead for Bytes4 {
-	fn abi_read(reader: &mut AbiReader) -> Result<Bytes4> {
-		reader.bytes4()
-	}
-}
-
-impl<T: AbiWrite> AbiWrite for &T {
-	fn abi_write(&self, writer: &mut AbiWriter) {
-		T::abi_write(self, writer);
-	}
-}
-
-impl<T: AbiType> AbiType for &T {
-	const SIGNATURE: SignatureUnit = T::SIGNATURE;
-
-	fn is_dynamic() -> bool {
-		T::is_dynamic()
-	}
-
-	fn size() -> usize {
-		T::size()
-	}
-}
-
-impl<T: AbiType + AbiRead + sealed::CanBePlacedInVec> AbiRead for Vec<T> {
-	fn abi_read(reader: &mut AbiReader) -> Result<Vec<T>> {
-		let mut sub = reader.subresult(None)?;
-		let size = sub.uint32()? as usize;
-		sub.subresult_offset = sub.offset;
-		let is_dynamic = <T as AbiType>::is_dynamic();
-		let mut out = Vec::with_capacity(size);
-		for _ in 0..size {
-			out.push(<T as AbiRead>::abi_read(&mut sub)?);
-			if !is_dynamic {
-				sub.bytes_read(<T as AbiType>::size());
-			};
-		}
-		Ok(out)
-	}
-}
-
-impl<T: AbiType> AbiType for Vec<T> {
-	const SIGNATURE: SignatureUnit = make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
-
-	fn is_dynamic() -> bool {
-		true
-	}
-
-	fn size() -> usize {
-		ABI_ALIGNMENT
-	}
-}
-
-impl<T: AbiWrite + AbiType> AbiWrite for Vec<T> {
-	fn abi_write(&self, writer: &mut AbiWriter) {
-		let is_dynamic = T::is_dynamic();
-		let mut sub = if is_dynamic {
-			AbiWriter::new_dynamic(is_dynamic)
-		} else {
-			AbiWriter::new()
-		};
-
-		// Write items count
-		(self.len() as u32).abi_write(&mut sub);
-
-		for item in self {
-			item.abi_write(&mut sub);
-		}
-		writer.write_subresult(sub);
-	}
-}
-
-impl AbiWrite for () {
-	fn abi_write(&self, _writer: &mut AbiWriter) {}
-}
-
-/// This particular AbiWrite implementation should be split to another trait,
-/// which only implements `to_result`, but due to lack of specialization feature
-/// in stable Rust, we can't have blanket impl of this trait `for T where T: AbiWrite`,
-/// so here we abusing default trait methods for it
-impl<T: AbiWrite> AbiWrite for ResultWithPostInfo<T> {
-	fn abi_write(&self, _writer: &mut AbiWriter) {
-		debug_assert!(false, "shouldn't be called, see comment")
-	}
-	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {
-		match self {
-			Ok(v) => Ok(WithPostDispatchInfo {
-				post_info: v.post_info.clone(),
-				data: {
-					let mut out = AbiWriter::new();
-					v.data.abi_write(&mut out);
-					out
-				},
-			}),
-			Err(e) => Err(e.clone()),
-		}
-	}
-}
-
-macro_rules! impl_tuples {
-	($($ident:ident)+) => {
-		impl<$($ident: AbiType,)+> AbiType for ($($ident,)+)
-		where
-        $(
-            $ident: AbiType,
-        )+
-		{
-            const SIGNATURE: SignatureUnit = make_signature!(
-                new fixed("(")
-                $(nameof(<$ident>::SIGNATURE) fixed(","))+
-                shift_left(1)
-                fixed(")")
-            );
-
-			fn is_dynamic() -> bool {
-				false
-				$(
-					|| <$ident>::is_dynamic()
-				)*
-			}
-
-			fn size() -> usize {
-				0 $(+ <$ident>::size())+
-			}
-		}
-
-		impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}
-
-		impl<$($ident),+> AbiRead for ($($ident,)+)
-		where
-			Self: AbiType,
-			$($ident: AbiRead + AbiType,)+
-		{
-			fn abi_read(reader: &mut AbiReader) -> Result<($($ident,)+)> {
-				let is_dynamic = <Self>::is_dynamic();
-				let size = if !is_dynamic { Some(<Self>::size()) } else { None };
-				let mut subresult = reader.subresult(size)?;
-				Ok((
-					$({
-						let value = <$ident>::abi_read(&mut subresult)?;
-						if !is_dynamic {subresult.bytes_read(<$ident as AbiType>::size())};
-						value
-					},)+
-				))
-			}
-		}
-
-		#[allow(non_snake_case)]
-		impl<$($ident),+> AbiWrite for ($($ident,)+)
-		where
-			$($ident: AbiWrite + AbiType,)+
-		{
-			fn abi_write(&self, writer: &mut AbiWriter) {
-				let ($($ident,)+) = self;
-				if <Self as AbiType>::is_dynamic() {
-					let mut sub = AbiWriter::new();
-					$($ident.abi_write(&mut sub);)+
-					writer.write_subresult(sub);
-				} else {
-					$($ident.abi_write(writer);)+
-				}
-			}
-		}
-	};
-}
-
-impl_tuples! {A}
-impl_tuples! {A B}
-impl_tuples! {A B C}
-impl_tuples! {A B C D}
-impl_tuples! {A B C D E}
-impl_tuples! {A B C D E F}
-impl_tuples! {A B C D E F G}
-impl_tuples! {A B C D E F G H}
-impl_tuples! {A B C D E F G H I}
-impl_tuples! {A B C D E F G H I J}
-
-//----- impls for Option -----
-impl<T: AbiType> AbiType for Option<T> {
-	const SIGNATURE: SignatureUnit = <(bool, T)>::SIGNATURE;
-
-	fn is_dynamic() -> bool {
-		<(bool, T)>::is_dynamic()
-	}
-
-	fn size() -> usize {
-		<(bool, T)>::size()
-	}
-}
-
-impl<T: AbiWrite + AbiType + Default> AbiWrite for Option<T> {
-	fn abi_write(&self, writer: &mut AbiWriter) {
-		match self {
-			Some(value) => (true, value).abi_write(writer),
-			None => (false, T::default()).abi_write(writer),
-		}
-	}
-}
-
-impl<T> AbiRead for Option<T>
-where
-	Self: AbiType,
-	T: AbiRead + AbiType,
-{
-	fn abi_read(reader: &mut AbiReader) -> Result<Self>
-	where
-		Self: Sized,
-	{
-		let (status, value) = <(bool, T)>::abi_read(reader)?;
-		Ok(if status { Some(value) } else { None })
-	}
-}
deletedcrates/evm-coder/src/abi/mod.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi/mod.rs
+++ /dev/null
@@ -1,348 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Implementation of EVM RLP reader/writer
-
-#![allow(dead_code)]
-
-mod traits;
-pub use traits::*;
-mod impls;
-
-#[cfg(test)]
-mod test;
-
-#[cfg(not(feature = "std"))]
-use alloc::vec::Vec;
-use evm_core::ExitError;
-use primitive_types::{H160, U256};
-
-use crate::{
-	execution::{Result, Error},
-	types::*,
-};
-
-const ABI_ALIGNMENT: usize = 32;
-
-/// View into RLP data, which provides method to read typed items from it
-#[derive(Clone)]
-pub struct AbiReader<'i> {
-	buf: &'i [u8],
-	subresult_offset: usize,
-	offset: usize,
-}
-impl<'i> AbiReader<'i> {
-	/// Start reading RLP buffer, assuming there is no padding bytes
-	pub fn new(buf: &'i [u8]) -> Self {
-		Self {
-			buf,
-			subresult_offset: 0,
-			offset: 0,
-		}
-	}
-	/// Start reading RLP buffer, parsing first 4 bytes as selector
-	pub fn new_call(buf: &'i [u8]) -> Result<(Bytes4, Self)> {
-		if buf.len() < 4 {
-			return Err(Error::Error(ExitError::OutOfOffset));
-		}
-		let mut method_id = [0; 4];
-		method_id.copy_from_slice(&buf[0..4]);
-
-		Ok((
-			method_id,
-			Self {
-				buf,
-				subresult_offset: 4,
-				offset: 4,
-			},
-		))
-	}
-
-	fn read_pad<const S: usize>(
-		buf: &[u8],
-		offset: usize,
-		pad_start: usize,
-		pad_end: usize,
-		block_start: usize,
-		block_end: usize,
-	) -> Result<[u8; S]> {
-		if buf.len() - offset < ABI_ALIGNMENT {
-			return Err(Error::Error(ExitError::OutOfOffset));
-		}
-		let mut block = [0; S];
-		let is_pad_zeroed = buf[pad_start..pad_end].iter().all(|&v| v == 0);
-		if !is_pad_zeroed {
-			return Err(Error::Error(ExitError::InvalidRange));
-		}
-		block.copy_from_slice(&buf[block_start..block_end]);
-		Ok(block)
-	}
-
-	fn read_padleft<const S: usize>(&mut self) -> Result<[u8; S]> {
-		let offset = self.offset;
-		self.offset += ABI_ALIGNMENT;
-		Self::read_pad(
-			self.buf,
-			offset,
-			offset,
-			offset + ABI_ALIGNMENT - S,
-			offset + ABI_ALIGNMENT - S,
-			offset + ABI_ALIGNMENT,
-		)
-	}
-
-	fn read_padright<const S: usize>(&mut self) -> Result<[u8; S]> {
-		let offset = self.offset;
-		self.offset += ABI_ALIGNMENT;
-		Self::read_pad(
-			self.buf,
-			offset,
-			offset + S,
-			offset + ABI_ALIGNMENT,
-			offset,
-			offset + S,
-		)
-	}
-
-	/// Read [`H160`] at current position, then advance
-	pub fn address(&mut self) -> Result<H160> {
-		Ok(H160(self.read_padleft()?))
-	}
-
-	/// Read [`bool`] at current position, then advance
-	pub fn bool(&mut self) -> Result<bool> {
-		let data: [u8; 1] = self.read_padleft()?;
-		match data[0] {
-			0 => Ok(false),
-			1 => Ok(true),
-			_ => Err(Error::Error(ExitError::InvalidRange)),
-		}
-	}
-
-	/// Read [`[u8; 4]`] at current position, then advance
-	pub fn bytes4(&mut self) -> Result<[u8; 4]> {
-		self.read_padright()
-	}
-
-	/// Read [`Vec<u8>`] at current position, then advance
-	pub fn bytes(&mut self) -> Result<Vec<u8>> {
-		let mut subresult = self.subresult(None)?;
-		let length = subresult.uint32()? as usize;
-		if subresult.buf.len() < subresult.offset + length {
-			return Err(Error::Error(ExitError::OutOfOffset));
-		}
-		Ok(subresult.buf[subresult.offset..subresult.offset + length].into())
-	}
-
-	/// Read [`string`] at current position, then advance
-	pub fn string(&mut self) -> Result<String> {
-		String::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))
-	}
-
-	/// Read [`u8`] at current position, then advance
-	pub fn uint8(&mut self) -> Result<u8> {
-		Ok(self.read_padleft::<1>()?[0])
-	}
-
-	/// Read [`u32`] at current position, then advance
-	pub fn uint32(&mut self) -> Result<u32> {
-		Ok(u32::from_be_bytes(self.read_padleft()?))
-	}
-
-	/// Read [`u128`] at current position, then advance
-	pub fn uint128(&mut self) -> Result<u128> {
-		Ok(u128::from_be_bytes(self.read_padleft()?))
-	}
-
-	/// Read [`U256`] at current position, then advance
-	pub fn uint256(&mut self) -> Result<U256> {
-		let buf: [u8; 32] = self.read_padleft()?;
-		Ok(U256::from_big_endian(&buf))
-	}
-
-	/// Read [`u64`] at current position, then advance
-	pub fn uint64(&mut self) -> Result<u64> {
-		Ok(u64::from_be_bytes(self.read_padleft()?))
-	}
-
-	/// Read [`usize`] at current position, then advance
-	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]
-	pub fn read_usize(&mut self) -> Result<usize> {
-		Ok(usize::from_be_bytes(self.read_padleft()?))
-	}
-
-	/// Slice recursive buffer, advance one word for buffer offset
-	/// If `size` is [`None`] then [`Self::offset`] and [`Self::subresult_offset`] evals from [`Self::buf`].
-	pub fn subresult(&mut self, size: Option<usize>) -> Result<AbiReader<'i>> {
-		let subresult_offset = self.subresult_offset;
-		let offset = if let Some(size) = size {
-			self.offset += size;
-			0
-		} else {
-			self.uint32()? as usize
-		};
-
-		if offset + self.subresult_offset > self.buf.len() {
-			return Err(Error::Error(ExitError::InvalidRange));
-		}
-
-		let new_offset = offset + subresult_offset;
-		Ok(AbiReader {
-			buf: self.buf,
-			subresult_offset: new_offset,
-			offset: new_offset,
-		})
-	}
-
-	/// Notify about readed data portion.
-	pub fn bytes_read(&mut self, size: usize) {
-		self.subresult_offset += size;
-	}
-
-	/// Is this parser reached end of buffer?
-	pub fn is_finished(&self) -> bool {
-		self.buf.len() == self.offset
-	}
-}
-
-/// Writer for RLP encoded data
-#[derive(Default)]
-pub struct AbiWriter {
-	static_part: Vec<u8>,
-	dynamic_part: Vec<(usize, AbiWriter)>,
-	had_call: bool,
-	is_dynamic: bool,
-}
-impl AbiWriter {
-	/// Initialize internal buffers for output data, assuming no padding required
-	pub fn new() -> Self {
-		Self::default()
-	}
-
-	/// Initialize internal buffers with data size
-	pub fn new_dynamic(is_dynamic: bool) -> Self {
-		Self {
-			is_dynamic,
-			..Default::default()
-		}
-	}
-	/// Initialize internal buffers, inserting method selector at beginning
-	pub fn new_call(method_id: u32) -> Self {
-		let mut val = Self::new();
-		val.static_part.extend(&method_id.to_be_bytes());
-		val.had_call = true;
-		val
-	}
-
-	fn write_padleft(&mut self, block: &[u8]) {
-		assert!(block.len() <= ABI_ALIGNMENT);
-		self.static_part
-			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);
-		self.static_part.extend(block);
-	}
-
-	fn write_padright(&mut self, block: &[u8]) {
-		assert!(block.len() <= ABI_ALIGNMENT);
-		self.static_part.extend(block);
-		self.static_part
-			.extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);
-	}
-
-	/// Write [`H160`] to end of buffer
-	pub fn address(&mut self, address: &H160) {
-		self.write_padleft(&address.0)
-	}
-
-	/// Write [`bool`] to end of buffer
-	pub fn bool(&mut self, value: &bool) {
-		self.write_padleft(&[if *value { 1 } else { 0 }])
-	}
-
-	/// Write [`u8`] to end of buffer
-	pub fn uint8(&mut self, value: &u8) {
-		self.write_padleft(&[*value])
-	}
-
-	/// Write [`u32`] to end of buffer
-	pub fn uint32(&mut self, value: &u32) {
-		self.write_padleft(&u32::to_be_bytes(*value))
-	}
-
-	/// Write [`u64`] to end of buffer
-	pub fn uint64(&mut self, value: &u64) {
-		self.write_padleft(&u64::to_be_bytes(*value))
-	}
-
-	/// Write [`u128`] to end of buffer
-	pub fn uint128(&mut self, value: &u128) {
-		self.write_padleft(&u128::to_be_bytes(*value))
-	}
-
-	/// Write [`U256`] to end of buffer
-	pub fn uint256(&mut self, value: &U256) {
-		let mut out = [0; 32];
-		value.to_big_endian(&mut out);
-		self.write_padleft(&out)
-	}
-
-	/// Write [`usize`] to end of buffer
-	#[deprecated = "dangerous, as usize may have different width in wasm and native execution"]
-	pub fn write_usize(&mut self, value: &usize) {
-		self.write_padleft(&usize::to_be_bytes(*value))
-	}
-
-	/// Append recursive data, writing pending offset at end of buffer
-	pub fn write_subresult(&mut self, result: Self) {
-		self.dynamic_part.push((self.static_part.len(), result));
-		// Empty block, to be filled later
-		self.write_padleft(&[]);
-	}
-
-	fn memory(&mut self, value: &[u8]) {
-		let mut sub = Self::new();
-		sub.uint32(&(value.len() as u32));
-		for chunk in value.chunks(ABI_ALIGNMENT) {
-			sub.write_padright(chunk);
-		}
-		self.write_subresult(sub);
-	}
-
-	/// Append recursive [`str`] at end of buffer
-	pub fn string(&mut self, value: &str) {
-		self.memory(value.as_bytes())
-	}
-
-	/// Append recursive [`[u8]`] at end of buffer
-	pub fn bytes(&mut self, value: &[u8]) {
-		self.memory(value)
-	}
-
-	/// Finish writer, concatenating all internal buffers
-	pub fn finish(mut self) -> Vec<u8> {
-		for (static_offset, part) in self.dynamic_part {
-			let part_offset = self.static_part.len()
-				- if self.had_call { 4 } else { 0 }
-				- if self.is_dynamic { ABI_ALIGNMENT } else { 0 };
-
-			let encoded_dynamic_offset = usize::to_be_bytes(part_offset);
-			let start = static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len();
-			let stop = static_offset + ABI_ALIGNMENT;
-			self.static_part[start..stop].copy_from_slice(&encoded_dynamic_offset);
-			self.static_part.extend(part.finish())
-		}
-		self.static_part
-	}
-}
deletedcrates/evm-coder/src/abi/test.rsdiffbeforeafterboth
before · crates/evm-coder/src/abi/test.rs
1use crate::{2	abi::{AbiRead, AbiWrite},3	types::*,4};56use super::{AbiReader, AbiWriter};7use hex_literal::hex;8use primitive_types::{H160, U256};910fn test_impl<T>(function_identifier: u32, decoded_data: T, encoded_data: &[u8])11where12	T: AbiWrite + AbiRead + std::cmp::PartialEq + std::fmt::Debug,13{14	let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();15	assert_eq!(call, u32::to_be_bytes(function_identifier));16	let data = <T>::abi_read(&mut decoder).unwrap();17	assert_eq!(data, decoded_data);1819	let mut writer = AbiWriter::new_call(function_identifier);20	decoded_data.abi_write(&mut writer);21	let ed = writer.finish();22	similar_asserts::assert_eq!(encoded_data, ed.as_slice());23}2425macro_rules! test_impl_uint {26	($type:ident) => {27		test_impl::<$type>(28			0xdeadbeef,29			255 as $type,30			&hex!(31				"32                    deadbeef33                    00000000000000000000000000000000000000000000000000000000000000ff34                "35			),36		);37	};38}3940#[test]41fn encode_decode_uint8() {42	test_impl_uint!(u8);43}4445#[test]46fn encode_decode_uint32() {47	test_impl_uint!(u32);48}4950#[test]51fn encode_decode_uint128() {52	test_impl_uint!(u128);53}5455#[test]56fn encode_decode_uint256() {57	test_impl::<U256>(58		0xdeadbeef,59		U256([255, 0, 0, 0]),60		&hex!(61			"62                deadbeef63                00000000000000000000000000000000000000000000000000000000000000ff64            "65		),66	);67}6869#[test]70fn encode_decode_string() {71	test_impl::<String>(72		0xdeadbeef,73		"some string".to_string(),74		&hex!(75			"76                deadbeef77                000000000000000000000000000000000000000000000000000000000000002078                000000000000000000000000000000000000000000000000000000000000000b79                736f6d6520737472696e6700000000000000000000000000000000000000000080            "81		),82	);83}8485#[test]86fn encode_decode_tuple_string() {87	test_impl::<(String,)>(88		0xdeadbeef,89		("some string".to_string(),),90		&hex!(91			"92                deadbeef93                000000000000000000000000000000000000000000000000000000000000002094                000000000000000000000000000000000000000000000000000000000000002095                000000000000000000000000000000000000000000000000000000000000000b96                736f6d6520737472696e6700000000000000000000000000000000000000000097            "98		),99	);100}101102#[test]103fn encode_decode_vec_tuple_address_uint256() {104	test_impl::<Vec<(Address, U256)>>(105        0x1ACF2D55,106        vec![107            (108                H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),109                U256([10, 0, 0, 0]),110            ),111            (112                H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),113                U256([20, 0, 0, 0]),114            ),115            (116                H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),117                U256([30, 0, 0, 0]),118            ),119        ],120        &hex!(121            "122                1ACF2D55123                0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]124                0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]125126                0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address127                000000000000000000000000000000000000000000000000000000000000000A // uint256128129                000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address130                0000000000000000000000000000000000000000000000000000000000000014 // uint256131132                0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address133                000000000000000000000000000000000000000000000000000000000000001E // uint256134            "135        )136    );137}138139#[test]140fn encode_decode_vec_tuple_uint256_string() {141	test_impl::<Vec<(U256, String)>>(142        0xdeadbeef,143        vec![144            (1.into(), "Test URI 0".to_string()),145            (11.into(), "Test URI 1".to_string()),146            (12.into(), "Test URI 2".to_string()),147        ],148        &hex!(149            "150                deadbeef151                0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[]152                0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]153154                0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem155                00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem156                0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem157158                0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60159                0000000000000000000000000000000000000000000000000000000000000040 // offset of string160                000000000000000000000000000000000000000000000000000000000000000a // size of string161                5465737420555249203000000000000000000000000000000000000000000000 // string162163                000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0164                0000000000000000000000000000000000000000000000000000000000000040 // offset of string165                000000000000000000000000000000000000000000000000000000000000000a // size of string166                5465737420555249203100000000000000000000000000000000000000000000 // string167168                000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160169                0000000000000000000000000000000000000000000000000000000000000040 // offset of string170                000000000000000000000000000000000000000000000000000000000000000a // size of string171                5465737420555249203200000000000000000000000000000000000000000000 // string172            "173        )174    );175}176177#[test]178fn dynamic_after_static() {179	let mut encoder = AbiWriter::new();180	encoder.bool(&true);181	encoder.string("test");182	let encoded = encoder.finish();183184	let mut encoder = AbiWriter::new();185	encoder.bool(&true);186	// Offset to subresult187	encoder.uint32(&(32 * 2));188	// Len of "test"189	encoder.uint32(&4);190	encoder.write_padright(&[b't', b'e', b's', b't']);191	let alternative_encoded = encoder.finish();192193	assert_eq!(encoded, alternative_encoded);194195	let mut decoder = AbiReader::new(&encoded);196	assert!(decoder.bool().unwrap());197	assert_eq!(decoder.string().unwrap(), "test");198}199200#[test]201fn mint_sample() {202	let (call, mut decoder) = AbiReader::new_call(&hex!(203		"204            50bb4e7f205            000000000000000000000000ad2c0954693c2b5404b7e50967d3481bea432374206            0000000000000000000000000000000000000000000000000000000000000001207            0000000000000000000000000000000000000000000000000000000000000060208            0000000000000000000000000000000000000000000000000000000000000008209            5465737420555249000000000000000000000000000000000000000000000000210        "211	))212	.unwrap();213	assert_eq!(call, u32::to_be_bytes(0x50bb4e7f));214	assert_eq!(215		format!("{:?}", decoder.address().unwrap()),216		"0xad2c0954693c2b5404b7e50967d3481bea432374"217	);218	assert_eq!(decoder.uint32().unwrap(), 1);219	assert_eq!(decoder.string().unwrap(), "Test URI");220}221222#[test]223fn parse_vec_with_dynamic_type() {224	let decoded_data = (225		0x36543006,226		vec![227			(1.into(), "Test URI 0".to_string()),228			(11.into(), "Test URI 1".to_string()),229			(12.into(), "Test URI 2".to_string()),230		],231	);232233	let encoded_data = &hex!(234        "235            36543006236            00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address237            0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]238            0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]239240            0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem241            00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem242            0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem243244            0000000000000000000000000000000000000000000000000000000000000001 // first token id?   					#60245            0000000000000000000000000000000000000000000000000000000000000040 // offset of string246            000000000000000000000000000000000000000000000000000000000000000a // size of string247            5465737420555249203000000000000000000000000000000000000000000000 // string248249            000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11?			#e0250            0000000000000000000000000000000000000000000000000000000000000040 // offset of string251            000000000000000000000000000000000000000000000000000000000000000a // size of string252            5465737420555249203100000000000000000000000000000000000000000000 // string253254            000000000000000000000000000000000000000000000000000000000000000c // third token id?  Why ==12?			#160255            0000000000000000000000000000000000000000000000000000000000000040 // offset of string256            000000000000000000000000000000000000000000000000000000000000000a // size of string257            5465737420555249203200000000000000000000000000000000000000000000 // string258        "259    );260261	let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();262	assert_eq!(call, u32::to_be_bytes(decoded_data.0));263	let address = decoder.address().unwrap();264	let data = <Vec<(U256, String)>>::abi_read(&mut decoder).unwrap();265	assert_eq!(data, decoded_data.1);266267	let mut writer = AbiWriter::new_call(decoded_data.0);268	address.abi_write(&mut writer);269	decoded_data.1.abi_write(&mut writer);270	let ed = writer.finish();271	similar_asserts::assert_eq!(encoded_data, ed.as_slice());272}273274#[test]275fn encode_decode_vec_tuple_string_bytes() {276	test_impl::<Vec<(String, Bytes)>>(277		0xdeadbeef,278		vec![279			(280				"Test URI 0".to_string(),281				Bytes(vec![282					0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,283					0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,284					0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,285					0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,286				]),287			),288			(289				"Test URI 1".to_string(),290				Bytes(vec![291					0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,292					0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,293					0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,294					0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,295				]),296			),297			("Test URI 2".to_string(), Bytes(vec![0x33, 0x33])),298		],299		&hex!(300			"301                deadbeef302                0000000000000000000000000000000000000000000000000000000000000020303                0000000000000000000000000000000000000000000000000000000000000003304305                0000000000000000000000000000000000000000000000000000000000000060306                0000000000000000000000000000000000000000000000000000000000000140307                0000000000000000000000000000000000000000000000000000000000000220308309                0000000000000000000000000000000000000000000000000000000000000040310                0000000000000000000000000000000000000000000000000000000000000080311                000000000000000000000000000000000000000000000000000000000000000a312                5465737420555249203000000000000000000000000000000000000000000000313                0000000000000000000000000000000000000000000000000000000000000030314                1111111111111111111111111111111111111111111111111111111111111111315                1111111111111111111111111111111100000000000000000000000000000000316317                0000000000000000000000000000000000000000000000000000000000000040318                0000000000000000000000000000000000000000000000000000000000000080319                000000000000000000000000000000000000000000000000000000000000000a320                5465737420555249203100000000000000000000000000000000000000000000321                000000000000000000000000000000000000000000000000000000000000002f322                2222222222222222222222222222222222222222222222222222222222222222323                2222222222222222222222222222220000000000000000000000000000000000324325                0000000000000000000000000000000000000000000000000000000000000040326                0000000000000000000000000000000000000000000000000000000000000080327                000000000000000000000000000000000000000000000000000000000000000a328                5465737420555249203200000000000000000000000000000000000000000000329                0000000000000000000000000000000000000000000000000000000000000002330                3333000000000000000000000000000000000000000000000000000000000000331            "332		),333	);334}335336#[test]337// #[ignore = "reason"]338fn encode_decode_tuple0_tuple1_uint8_tuple1_string_bytes_tuple1_uint8_bytes() {339	let int = 0xff;340	let by = Bytes(vec![0x11, 0x22, 0x33]);341	let string = "some string".to_string();342343	test_impl::<((u8,), (String, Bytes), (u8, Bytes))>(344		0xdeadbeef,345		((int,), (string.clone(), by.clone()), (int, by)),346		&hex!(347			"348                deadbeef349                0000000000000000000000000000000000000000000000000000000000000020350                00000000000000000000000000000000000000000000000000000000000000ff351                0000000000000000000000000000000000000000000000000000000000000060352                0000000000000000000000000000000000000000000000000000000000000120353                0000000000000000000000000000000000000000000000000000000000000040354                0000000000000000000000000000000000000000000000000000000000000080355                000000000000000000000000000000000000000000000000000000000000000b356                736f6d6520737472696e67000000000000000000000000000000000000000000357                0000000000000000000000000000000000000000000000000000000000000003358                1122330000000000000000000000000000000000000000000000000000000000359                00000000000000000000000000000000000000000000000000000000000000ff360                0000000000000000000000000000000000000000000000000000000000000040361                0000000000000000000000000000000000000000000000000000000000000003362                1122330000000000000000000000000000000000000000000000000000000000363            "364		),365	);366}367368#[test]369fn encode_decode_tuple0_tuple1_uint8_tuple1_uint8_uint8_tuple1_uint8_uint8() {370	test_impl::<((u8,), (u8, u8), (u8, u8))>(371		0xdeadbeef,372		((43,), (44, 45), (46, 47)),373		&hex!(374			"375                deadbeef376                000000000000000000000000000000000000000000000000000000000000002b377                000000000000000000000000000000000000000000000000000000000000002c378                000000000000000000000000000000000000000000000000000000000000002d379                000000000000000000000000000000000000000000000000000000000000002e380                000000000000000000000000000000000000000000000000000000000000002f381            "382		),383	);384}385386#[test]387fn encode_decode_tuple0_tuple1_uint8_tuple1_uint8() {388	test_impl::<((u8,), (u8,))>(389		0xdeadbeef,390		((43,), (44,)),391		&hex!(392			"393                deadbeef394                000000000000000000000000000000000000000000000000000000000000002b395                000000000000000000000000000000000000000000000000000000000000002c396            "397		),398	);399}400401#[test]402fn encode_decode_tuple0_tuple1_uint8_uint8() {403	test_impl::<((u8, u8),)>(404		0xdeadbeef,405		((43, 44),),406		&hex!(407			"408                deadbeef409                000000000000000000000000000000000000000000000000000000000000002b410                000000000000000000000000000000000000000000000000000000000000002c411            "412		),413	);414}415416#[test]417fn encode_decode_tuple_uint8_uint8() {418	test_impl::<(u8, u8)>(419		0xdeadbeef,420		(43, 44),421		&hex!(422			"423                deadbeef424                000000000000000000000000000000000000000000000000000000000000002b425                000000000000000000000000000000000000000000000000000000000000002c426            "427		),428	);429}430431#[test]432fn encode_decode_tuple0_tuple1_uint8_uint8_tuple1_uint8_uint8_and_uint8() {433	test_impl::<((u8, u8), (u8, u8), u8)>(434		0xdeadbeef,435		((10, 11), (12, 13), 14),436		&hex!(437			"438                deadbeef439                000000000000000000000000000000000000000000000000000000000000000a440                000000000000000000000000000000000000000000000000000000000000000b441                000000000000000000000000000000000000000000000000000000000000000c442                000000000000000000000000000000000000000000000000000000000000000d443                000000000000000000000000000000000000000000000000000000000000000e444            "445		),446	);447}448449#[test]450fn encode_decode_tuple0_tuple1_string() {451	test_impl::<((String,),)>(452		0xdeadbeef,453		(("some string".to_string(),),),454		&hex!(455			"456                deadbeef457                0000000000000000000000000000000000000000000000000000000000000020458                0000000000000000000000000000000000000000000000000000000000000020459                0000000000000000000000000000000000000000000000000000000000000020460                000000000000000000000000000000000000000000000000000000000000000b461                736f6d6520737472696e67000000000000000000000000000000000000000000462            "463		),464	);465}466467#[test]468fn encode_decode_tuple0_tuple1_uint8_string() {469	test_impl::<((u8, String),)>(470		0xdeadbeef,471		((0xff, "some string".to_string()),),472		&hex!(473			"474                deadbeef475                0000000000000000000000000000000000000000000000000000000000000020476                0000000000000000000000000000000000000000000000000000000000000020477                00000000000000000000000000000000000000000000000000000000000000ff478                0000000000000000000000000000000000000000000000000000000000000040479                000000000000000000000000000000000000000000000000000000000000000b480                736f6d6520737472696e67000000000000000000000000000000000000000000481            "482		),483	);484}485486#[test]487fn encode_decode_tuple0_tuple1_string_bytes() {488	test_impl::<((String, Bytes),)>(489		0xdeadbeef,490		(("some string".to_string(), Bytes(vec![1, 2, 3])),),491		&hex!(492			"493                deadbeef494                0000000000000000000000000000000000000000000000000000000000000020495                0000000000000000000000000000000000000000000000000000000000000020496                0000000000000000000000000000000000000000000000000000000000000040497                0000000000000000000000000000000000000000000000000000000000000080498                000000000000000000000000000000000000000000000000000000000000000b499                736f6d6520737472696e67000000000000000000000000000000000000000000500                0000000000000000000000000000000000000000000000000000000000000003501                0102030000000000000000000000000000000000000000000000000000000000502            "503		),504	);505}506507#[test]508fn encode_decode_tuple0_tuple1_uint8_tuple1_string() {509	test_impl::<((u8,), (String,))>(510		0xdeadbeef,511		((0xff,), ("some string".to_string(),)),512		&hex!(513			"514                deadbeef515                0000000000000000000000000000000000000000000000000000000000000020516                00000000000000000000000000000000000000000000000000000000000000ff517                0000000000000000000000000000000000000000000000000000000000000040518                0000000000000000000000000000000000000000000000000000000000000020519                000000000000000000000000000000000000000000000000000000000000000b520                736f6d6520737472696e67000000000000000000000000000000000000000000521            "522		),523	);524}525526#[test]527fn parse_multiple_params() {528	let encoded_data = hex!(529		"530            deadbeef531            000000000000000000000000000000000000000000000000000000000000000a532            000000000000000000000000000000000000000000000000000000000000000b533        "534	);535	let (_, mut decoder) = AbiReader::new_call(&encoded_data).unwrap();536	let p1 = <u8>::abi_read(&mut decoder).unwrap();537	let p2 = <u8>::abi_read(&mut decoder).unwrap();538	assert_eq!(p1, 0x0a);539	assert_eq!(p2, 0x0b);540}541542#[test]543fn encode_decode_option_uint8_some() {544	test_impl::<Option<u8>>(545		0xdeadbeef,546		Some(44),547		&hex!(548			"549                deadbeef550                0000000000000000000000000000000000000000000000000000000000000001551                000000000000000000000000000000000000000000000000000000000000002c552            "553		),554	);555}556557#[test]558fn encode_decode_option_uint8_none() {559	test_impl::<Option<u8>>(560		0xdeadbeef,561		None,562		&hex!(563			"564                deadbeef565                0000000000000000000000000000000000000000000000000000000000000000566                0000000000000000000000000000000000000000000000000000000000000000567            "568		),569	);570}571572#[test]573fn encode_decode_option_string_some() {574	test_impl::<Option<String>>(575		0xdeadbeef,576		Some("some string".to_string()),577		&hex!(578			"579                deadbeef580                0000000000000000000000000000000000000000000000000000000000000020581                0000000000000000000000000000000000000000000000000000000000000001582                0000000000000000000000000000000000000000000000000000000000000040583                000000000000000000000000000000000000000000000000000000000000000b584                736f6d6520737472696e67000000000000000000000000000000000000000000585            "586		),587	);588}589590#[test]591fn encode_decode_option_string_none() {592	test_impl::<Option<String>>(593		0xdeadbeef,594		None,595		&hex!(596			"597                deadbeef598                0000000000000000000000000000000000000000000000000000000000000020599                0000000000000000000000000000000000000000000000000000000000000000600                0000000000000000000000000000000000000000000000000000000000000040601                0000000000000000000000000000000000000000000000000000000000000000602            "603		),604	);605}
deletedcrates/evm-coder/src/abi/traits.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/abi/traits.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-use super::{AbiReader, AbiWriter};
-use crate::{
-	custom_signature::*,
-	execution::{Result, ResultWithPostInfo},
-};
-use core::str::from_utf8;
-
-/// Helper for type.
-pub trait AbiType {
-	/// Signature for Etherium ABI.
-	const SIGNATURE: SignatureUnit;
-
-	/// Signature as str.
-	fn as_str() -> &'static str {
-		from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
-	}
-
-	/// Is type dynamic sized.
-	fn is_dynamic() -> bool;
-
-	/// Size for type aligned to [`ABI_ALIGNMENT`].
-	fn size() -> usize;
-}
-
-/// [`AbiReader`] implements reading of many types.
-pub trait AbiRead {
-	/// Read item from current position, advanding decoder
-	fn abi_read(reader: &mut AbiReader) -> Result<Self>
-	where
-		Self: Sized;
-}
-
-/// For questions about inability to provide custom implementations,
-/// see [`AbiRead`]
-pub trait AbiWrite {
-	/// Write value to end of specified encoder
-	fn abi_write(&self, writer: &mut AbiWriter);
-	/// Specialization for [`crate::solidity_interface`] implementation,
-	/// see comment in `impl AbiWrite for ResultWithPostInfo`
-	fn to_result(&self) -> ResultWithPostInfo<AbiWriter> {
-		let mut writer = AbiWriter::new();
-		self.abi_write(&mut writer);
-		Ok(writer.into())
-	}
-}
deletedcrates/evm-coder/src/custom_signature.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/custom_signature.rs
+++ /dev/null
@@ -1,326 +0,0 @@
-//! # A module for custom signature support.
-//!
-//! ## Overview
-//! This module allows you to create arbitrary signatures for types and functions in compile time.
-//!
-//! ### Type signatures
-//! To create the desired type signature, you need to create your own trait with the `SIGNATURE` constant.
-//! Then in the implementation, for the required type, use the macro [`make_signature`]
-//! #### Example
-//! ```
-//! use std::str::from_utf8;
-//! use evm_coder::{custom_signature::SignatureUnit, make_signature};
-//!
-//! // Create trait for our signature
-//! trait SoliditySignature {
-//!     const SIGNATURE: SignatureUnit;
-//!
-//!     fn name() -> &'static str {
-//!         from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
-//!     }
-//! }
-//!
-//! // Make signatures for some types
-//! impl SoliditySignature for u8 {
-//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));
-//! }
-//! impl SoliditySignature for u32 {
-//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint32"));
-//! }
-//! impl<T: SoliditySignature> SoliditySignature for Vec<T> {
-//!     const SIGNATURE: SignatureUnit = make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
-//! }
-//! impl<A: SoliditySignature, B: SoliditySignature> SoliditySignature for (A, B) {
-//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("(") nameof(A::SIGNATURE) fixed(",") nameof(B::SIGNATURE) fixed(")"));
-//! }
-//! impl<A: SoliditySignature> SoliditySignature for (A,) {
-//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("(") nameof(A::SIGNATURE) fixed(",") shift_left(1) fixed(")"));
-//! }
-//!
-//! assert_eq!(u8::name(), "uint8");
-//! assert_eq!(<Vec<u8>>::name(), "uint8[]");
-//! assert_eq!(<(u32, u8)>::name(), "(uint32,uint8)");
-//! ```
-//!
-//! ### Function signatures
-//! To create a function signature, the macro [`make_signature`] is also used, which accepts
-//! settings for the function format [`SignaturePreferences`] and function parameters [`SignatureUnit`]
-//! #### Example
-//! ```
-//! use core::str::from_utf8;
-//! use evm_coder::{custom_signature::SignatureUnit, make_signature};
-//! // Trait for our signature
-//! trait SoliditySignature {
-//!     const SIGNATURE: SignatureUnit;
-//!
-//!     fn name() -> &'static str {
-//!         from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
-//!     }
-//! }
-//!
-//! // Make signatures for some types
-//! impl SoliditySignature for u8 {
-//!     const SIGNATURE: SignatureUnit = make_signature!(new fixed("uint8"));
-//! }
-//! impl<T: SoliditySignature> SoliditySignature for Vec<T> {
-//!     const SIGNATURE: SignatureUnit = make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
-//! }
-//! ```
-
-/// The maximum length of the signature.
-pub const SIGNATURE_SIZE_LIMIT: usize = 256;
-
-/// Storage for the signature or its elements.
-#[derive(Debug)]
-pub struct SignatureUnit {
-	/// Signature data.
-	pub data: [u8; SIGNATURE_SIZE_LIMIT],
-	/// The actual size of the data.
-	pub len: usize,
-}
-
-impl SignatureUnit {
-	/// Create a signature from `&str'.
-	pub const fn new(name: &'static str) -> SignatureUnit {
-		let mut signature = [0_u8; SIGNATURE_SIZE_LIMIT];
-		let name = name.as_bytes();
-		let name_len = name.len();
-		let mut dst_offset = 0;
-		crate::make_signature!(@copy(name, signature, name_len, dst_offset));
-		SignatureUnit {
-			data: signature,
-			len: name_len,
-		}
-	}
-	/// String conversion
-	pub fn as_str(&self) -> Option<&str> {
-		core::str::from_utf8(&self.data[0..self.len]).ok()
-	}
-}
-
-/// ### Macro to create signatures of types and functions.
-///
-/// Format for creating a type of signature:
-/// ```ignore
-/// make_signature!(new fixed("uint8")); // Simple type
-/// make_signature!(new fixed("(") nameof(u8) fixed(",") nameof(u8) fixed(")")); // Composite type
-/// ```
-#[macro_export]
-macro_rules! make_signature {
-	(new $($tt:tt)*) => {
-		($crate::custom_signature::SignatureUnit {
-			data: {
-				let mut out = [0u8; $crate::custom_signature::SIGNATURE_SIZE_LIMIT];
-				let mut dst_offset = 0;
-				$crate::make_signature!(@data(out, dst_offset); $($tt)*);
-				out
-			},
-			len: {0 + $crate::make_signature!(@size; $($tt)*)},
-		})
-	};
-
-	(@size;) => {
-		0
-	};
-	(@size; fixed($expr:expr) $($tt:tt)*) => {
-		$expr.len() + $crate::make_signature!(@size; $($tt)*)
-	};
-	(@size; nameof($expr:expr) $($tt:tt)*) => {
-		$expr.len + $crate::make_signature!(@size; $($tt)*)
-	};
-	(@size; numof($expr:expr) $($tt:tt)*) => {
-		{
-			let mut out = 0;
-			let mut v = $expr;
-			if v == 0 {
-				out = 1;
-			} else {
-				while v > 0 {
-					out += 1;
-					v /= 10;
-				}
-			}
-			out
-		} + $crate::make_signature!(@size; $($tt)*)
-	};
-	(@size; shift_left($expr:expr) $($tt:tt)*) => {
-		$crate::make_signature!(@size; $($tt)*) - $expr
-	};
-
-	(@data($dst:ident, $dst_offset:ident);) => {};
-	(@data($dst:ident, $dst_offset:ident); fixed($expr:expr) $($tt:tt)*) => {
-		{
-			let data = $expr.as_bytes();
-			let data_len = data.len();
-			$crate::make_signature!(@copy(data, $dst, data_len, $dst_offset));
-		}
-		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
-	};
-	(@data($dst:ident, $dst_offset:ident); nameof($expr:expr) $($tt:tt)*) => {
-		{
-			$crate::make_signature!(@copy(&$expr.data, $dst, $expr.len, $dst_offset));
-		}
-		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
-	};
-	(@data($dst:ident, $dst_offset:ident); numof($expr:expr) $($tt:tt)*) => {
-		{
-			let mut v = $expr;
-			let mut need_to_swap = 0;
-			if v == 0 {
-				$dst[$dst_offset] = b'0';
-				$dst_offset += 1;
-			} else {
-				while v > 0 {
-					let n = (v % 10) as u8;
-					$dst[$dst_offset] = b'0' + n;
-					v /= 10;
-					need_to_swap += 1;
-					$dst_offset += 1;
-				}
-			}
-			let mut i = 0;
-			#[allow(clippy::manual_swap)]
-			while i < need_to_swap / 2 {
-				let a = $dst_offset - i - 1;
-				let b = $dst_offset - need_to_swap + i;
-				let v = $dst[a];
-				$dst[a] = $dst[b];
-				$dst[b] = v;
-				i += 1;
-			}
-		}
-		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
-	};
-	(@data($dst:ident, $dst_offset:ident); shift_left($expr:expr) $($tt:tt)*) => {
-		$dst_offset -= $expr;
-		$crate::make_signature!(@data($dst, $dst_offset); $($tt)*)
-	};
-
-	(@copy($src:expr, $dst:expr, $src_len:expr, $dst_offset:ident)) => {
-		{
-			let mut src_offset = 0;
-			let src_len: usize = $src_len;
-			while src_offset < src_len {
-				$dst[$dst_offset] = $src[src_offset];
-				$dst_offset += 1;
-				src_offset += 1;
-			}
-		}
-	}
-}
-
-#[cfg(test)]
-mod test {
-	use core::str::from_utf8;
-
-	use super::{SIGNATURE_SIZE_LIMIT, SignatureUnit};
-
-	trait Name {
-		const NAME: SignatureUnit;
-
-		fn name() -> &'static str {
-			from_utf8(&Self::NAME.data[..Self::NAME.len]).expect("bad utf-8")
-		}
-	}
-
-	impl Name for u8 {
-		const NAME: SignatureUnit = make_signature!(new fixed("uint8"));
-	}
-	impl Name for u32 {
-		const NAME: SignatureUnit = make_signature!(new fixed("uint32"));
-	}
-	impl<T: Name> Name for Vec<T> {
-		const NAME: SignatureUnit = make_signature!(new nameof(T::NAME) fixed("[]"));
-	}
-	impl<A: Name, B: Name> Name for (A, B) {
-		const NAME: SignatureUnit =
-			make_signature!(new fixed("(") nameof(A::NAME) fixed(",") nameof(B::NAME) fixed(")"));
-	}
-	impl<A: Name> Name for (A,) {
-		const NAME: SignatureUnit =
-			make_signature!(new fixed("(") nameof(A::NAME) fixed(",") shift_left(1) fixed(")"));
-	}
-	impl<A: Name, const SIZE: usize> Name for [A; SIZE] {
-		const NAME: SignatureUnit =
-			make_signature!(new nameof(A::NAME) fixed("[") numof(SIZE) fixed("]"));
-	}
-
-	struct MaxSize();
-	impl Name for MaxSize {
-		const NAME: SignatureUnit = SignatureUnit {
-			data: [b'!'; SIGNATURE_SIZE_LIMIT],
-			len: SIGNATURE_SIZE_LIMIT,
-		};
-	}
-
-	#[test]
-	fn simple() {
-		assert_eq!(u8::name(), "uint8");
-		assert_eq!(u32::name(), "uint32");
-	}
-
-	#[test]
-	fn vector_of_simple() {
-		assert_eq!(<Vec<u8>>::name(), "uint8[]");
-		assert_eq!(<Vec<u32>>::name(), "uint32[]");
-	}
-
-	#[test]
-	fn vector_of_vector() {
-		assert_eq!(<Vec<Vec<u8>>>::name(), "uint8[][]");
-	}
-
-	#[test]
-	fn tuple_of_simple() {
-		assert_eq!(<(u32, u8)>::name(), "(uint32,uint8)");
-	}
-
-	#[test]
-	fn tuple_of_tuple() {
-		assert_eq!(
-			<((u32, u8), (u8, u32))>::name(),
-			"((uint32,uint8),(uint8,uint32))"
-		);
-	}
-
-	#[test]
-	fn vector_of_tuple() {
-		assert_eq!(<Vec<(u32, u8)>>::name(), "(uint32,uint8)[]");
-	}
-
-	#[test]
-	fn tuple_of_vector() {
-		assert_eq!(<(Vec<u32>, u8)>::name(), "(uint32[],uint8)");
-	}
-
-	#[test]
-	fn complex() {
-		assert_eq!(
-			<(Vec<u32>, (u32, Vec<u8>))>::name(),
-			"(uint32[],(uint32,uint8[]))"
-		);
-	}
-
-	#[test]
-	fn max_size() {
-		assert_eq!(<MaxSize>::name(), "!".repeat(SIGNATURE_SIZE_LIMIT));
-	}
-
-	#[test]
-	fn shift() {
-		assert_eq!(<(u32,)>::name(), "(uint32)");
-	}
-
-	#[test]
-	fn num() {
-		assert_eq!(<[u8; 0]>::name(), "uint8[0]");
-		assert_eq!(<[u8; 1234]>::name(), "uint8[1234]");
-		assert_eq!(<[u8; 12345]>::name(), "uint8[12345]");
-	}
-
-	#[test]
-	fn over_max_size() {
-		let t = trybuild::TestCases::new();
-		t.compile_fail("tests/build_failed/custom_signature_over_max_size.rs");
-	}
-}
deletedcrates/evm-coder/src/events.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/events.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use ethereum::Log;
-use primitive_types::{H160, H256, U256};
-
-use crate::types::*;
-
-/// Implementation of this trait should not be written manually,
-/// instead use [`crate::ToLog`] proc macros.
-///
-/// See also [`evm_coder_procedural::ToLog`], [solidity docs on events](https://docs.soliditylang.org/en/develop/contracts.html#events)
-pub trait ToLog {
-	/// Convert event to [`ethereum::Log`].
-	/// Because event by itself doesn't contains current contract
-	/// address, it should be specified manually.
-	fn to_log(&self, contract: H160) -> Log;
-}
-
-/// Only items implementing `ToTopic` may be used as `#[indexed]` field
-/// in [`crate::ToLog`] macro usage.
-///
-/// See also (solidity docs on events)[<https://docs.soliditylang.org/en/develop/contracts.html#events>]
-pub trait ToTopic {
-	/// Convert value to topic to be used in [`ethereum::Log`]
-	fn to_topic(&self) -> H256;
-}
-
-impl ToTopic for H256 {
-	fn to_topic(&self) -> H256 {
-		*self
-	}
-}
-
-impl ToTopic for U256 {
-	fn to_topic(&self) -> H256 {
-		let mut out = [0u8; 32];
-		self.to_big_endian(&mut out);
-		H256(out)
-	}
-}
-
-impl ToTopic for Address {
-	fn to_topic(&self) -> H256 {
-		let mut out = [0u8; 32];
-		out[12..32].copy_from_slice(&self.0);
-		H256(out)
-	}
-}
-
-impl ToTopic for u32 {
-	fn to_topic(&self) -> H256 {
-		let mut out = [0u8; 32];
-		out[28..32].copy_from_slice(&self.to_be_bytes());
-		H256(out)
-	}
-}
deletedcrates/evm-coder/src/execution.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/execution.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Contract execution related types
-
-#[cfg(not(feature = "std"))]
-use alloc::string::{String, ToString};
-use evm_core::{ExitError, ExitFatal};
-#[cfg(feature = "std")]
-use std::string::{String, ToString};
-
-use crate::Weight;
-
-/// Execution error, should be convertible between EVM and Substrate.
-#[derive(Debug, Clone)]
-pub enum Error {
-	/// Non-fatal contract error occured
-	Revert(String),
-	/// EVM fatal error
-	Fatal(ExitFatal),
-	/// EVM normal error
-	Error(ExitError),
-}
-
-impl<E> From<E> for Error
-where
-	E: ToString,
-{
-	fn from(e: E) -> Self {
-		Self::Revert(e.to_string())
-	}
-}
-
-/// To be used in [`crate::solidity_interface`] implementation.
-pub type Result<T> = core::result::Result<T, Error>;
-
-/// Static information collected from [`crate::weight`].
-pub struct DispatchInfo {
-	/// Statically predicted call weight
-	pub weight: Weight,
-}
-
-impl From<Weight> for DispatchInfo {
-	fn from(weight: Weight) -> Self {
-		Self { weight }
-	}
-}
-impl From<u64> for DispatchInfo {
-	fn from(weight: u64) -> Self {
-		Self {
-			weight: Weight::from_ref_time(weight),
-		}
-	}
-}
-impl From<()> for DispatchInfo {
-	fn from(_: ()) -> Self {
-		Self {
-			weight: Weight::zero(),
-		}
-	}
-}
-
-/// Weight information that is only available post dispatch.
-/// Note: This can only be used to reduce the weight or fee, not increase it.
-#[derive(Default, Clone)]
-pub struct PostDispatchInfo {
-	/// Actual weight consumed by call
-	actual_weight: Option<Weight>,
-}
-
-impl PostDispatchInfo {
-	/// Calculate amount to be returned back to user
-	pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight {
-		info.weight - self.calc_actual_weight(info)
-	}
-
-	/// Calculate actual consumed weight, saturating to weight reported
-	/// pre-dispatch
-	pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight {
-		if let Some(actual_weight) = self.actual_weight {
-			actual_weight.min(info.weight)
-		} else {
-			info.weight
-		}
-	}
-}
-
-/// Wrapper for PostDispatchInfo and any user-provided data
-#[derive(Clone)]
-pub struct WithPostDispatchInfo<T> {
-	/// User provided data
-	pub data: T,
-	/// Info known after dispatch
-	pub post_info: PostDispatchInfo,
-}
-
-impl<T> From<T> for WithPostDispatchInfo<T> {
-	fn from(data: T) -> Self {
-		Self {
-			data,
-			post_info: Default::default(),
-		}
-	}
-}
-
-/// Return type of items in [`crate::solidity_interface`] definition
-pub type ResultWithPostInfo<T> =
-	core::result::Result<WithPostDispatchInfo<T>, WithPostDispatchInfo<Error>>;
deletedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/lib.rs
+++ /dev/null
@@ -1,298 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![doc = include_str!("../README.md")]
-#![deny(missing_docs)]
-#![macro_use]
-#![cfg_attr(not(feature = "std"), no_std)]
-#[cfg(not(feature = "std"))]
-extern crate alloc;
-
-use abi::{AbiRead, AbiReader, AbiWriter};
-pub use evm_coder_procedural::{event_topic, fn_selector};
-pub mod abi;
-pub use events::{ToLog, ToTopic};
-use execution::DispatchInfo;
-pub mod execution;
-#[macro_use]
-pub mod custom_signature;
-
-/// Derives call enum implementing [`crate::Callable`], [`crate::Weighted`]
-/// and [`crate::Call`] from impl block.
-///
-/// ## Macro syntax
-///
-/// `#[solidity_interface(name, is, inline_is, events)]`
-/// - *name* - used in generated code, and for Call enum name
-/// - *is* - used to provide inheritance in Solidity
-/// - *inline_is* - same as `is`, but ERC165::SupportsInterface will work differently: For `is` SupportsInterface(A) will return true
-///   if A is one of the interfaces the contract is inherited from (e.g. B is created as `is(A)`). If B is created as `inline_is(A)`
-///   SupportsInterface(A) will internally create a new interface that combines all methods of A and B, so SupportsInterface(A) will return
-///   false.
-///
-/// `#[weight(value)]`
-/// Can be added to every method of impl block, used for deriving [`crate::Weighted`], which
-/// is used by substrate bridge.
-/// - *value*: expression, which evaluates to weight required to call this method.
-/// This expression can use call arguments to calculate non-constant execution time.
-/// This expression should evaluate faster than actual execution does, and may provide worse case
-/// than one is called.
-///
-/// `#[solidity_interface(rename_selector)]`
-/// - *rename_selector* - by default, selector name will be generated by transforming method name
-/// from snake_case to camelCase. Use this option, if other naming convention is required.
-/// I.e: method `token_uri` will be automatically renamed to `tokenUri` in selector, but name
-/// required by ERC721 standard is `tokenURI`, thus we need to specify `rename_selector = "tokenURI"`
-/// explicitly.
-///
-/// Both contract and contract methods may have doccomments, which will end up in a generated
-/// solidity interface file, thus you should use [solidity syntax](https://docs.soliditylang.org/en/latest/natspec-format.html) for writing documentation in this macro
-///
-/// ## Example
-///
-/// ```ignore
-/// struct SuperContract;
-/// struct InlineContract;
-/// struct Contract;
-///
-/// #[derive(ToLog)]
-/// enum ContractEvents {
-///     Event(#[indexed] uint32),
-/// }
-///
-/// /// @dev This contract provides function to multiply two numbers
-/// #[solidity_interface(name = MyContract, is(SuperContract), inline_is(InlineContract))]
-/// impl Contract {
-///     /// Multiply two numbers
-///     /// @param a First number
-///     /// @param b Second number
-///     /// @return uint32 Product of two passed numbers
-///     /// @dev This function returns error in case of overflow
-///     #[weight(200 + a + b)]
-///     #[solidity_interface(rename_selector = "mul")]
-///     fn mul(&mut self, a: uint32, b: uint32) -> Result<uint32> {
-///         Ok(a.checked_mul(b).ok_or("overflow")?)
-///     }
-/// }
-/// ```
-pub use evm_coder_procedural::solidity_interface;
-/// See [`solidity_interface`]
-pub use evm_coder_procedural::solidity;
-/// See [`solidity_interface`]
-pub use evm_coder_procedural::weight;
-pub use evm_coder_procedural::AbiCoder;
-pub use sha3_const;
-
-/// macro reexports
-pub use ethereum;
-
-/// Derives [`ToLog`] for enum
-///
-/// Selectors will be derived from variant names, there is currently no way to have custom naming
-/// for them
-///
-/// `#[indexed]`
-/// Marks this field as indexed, so it will appear in [`ethereum::Log`] topics instead of data
-pub use evm_coder_procedural::ToLog;
-
-// Api of those modules shouldn't be consumed directly, it is only exported for usage in proc macros
-#[doc(hidden)]
-pub mod events;
-#[doc(hidden)]
-#[cfg(feature = "stubgen")]
-pub mod solidity;
-
-/// Sealed traits.
-pub mod sealed {
-	/// Not every type should be directly placed in vec.
-	/// Vec encoding is not memory efficient, as every item will be padded
-	/// to 32 bytes.
-	/// Instead you should use specialized types (`bytes` in case of `Vec<u8>`)
-	pub trait CanBePlacedInVec {}
-}
-
-/// Solidity type definitions (aliases from solidity name to rust type)
-/// To be used in [`solidity_interface`] definitions, to make sure there is no
-/// type conflict between Rust code and generated definitions
-pub mod types {
-	#![allow(non_camel_case_types, missing_docs)]
-
-	#[cfg(not(feature = "std"))]
-	use alloc::{vec::Vec};
-	use primitive_types::{U256, H160, H256};
-
-	pub type Address = H160;
-	pub type Bytes4 = [u8; 4];
-	pub type Topic = H256;
-
-	#[cfg(not(feature = "std"))]
-	pub type String = ::alloc::string::String;
-	#[cfg(feature = "std")]
-	pub type String = ::std::string::String;
-
-	#[derive(Default, Debug, PartialEq, Eq, Clone)]
-	pub struct Bytes(pub Vec<u8>);
-
-	//#region Special types
-	/// Makes function payable
-	pub type Value = U256;
-	/// Makes function caller-sensitive
-	pub type Caller = Address;
-	//#endregion
-
-	/// Ethereum typed call message, similar to solidity
-	/// `msg` object.
-	pub struct Msg<C> {
-		pub call: C,
-		/// Address of user, which called this contract.
-		pub caller: H160,
-		/// Payment amount to contract.
-		/// Contract should reject payment, if target call is not payable,
-		/// and there is no `receiver()` function defined.
-		pub value: U256,
-	}
-
-	impl From<Vec<u8>> for Bytes {
-		fn from(src: Vec<u8>) -> Self {
-			Self(src)
-		}
-	}
-
-	#[allow(clippy::from_over_into)]
-	impl Into<Vec<u8>> for Bytes {
-		fn into(self) -> Vec<u8> {
-			self.0
-		}
-	}
-
-	impl Bytes {
-		#[must_use]
-		pub fn len(&self) -> usize {
-			self.0.len()
-		}
-
-		#[must_use]
-		pub fn is_empty(&self) -> bool {
-			self.len() == 0
-		}
-	}
-}
-
-/// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macro
-pub trait Call: Sized {
-	/// Parse call buffer into typed call enum
-	fn parse(selector: types::Bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>>;
-}
-
-/// Intended to be used as `#[weight]` output type
-/// Should be same between evm-coder and substrate to avoid confusion
-///
-/// Isn't same thing as gas, some mapping is required between those types
-pub type Weight = frame_support::pallet_prelude::Weight;
-
-/// In substrate, we have benchmarking, which allows
-/// us to not rely on gas metering, but instead predict amount of gas to execute call
-pub trait Weighted: Call {
-	/// Predict weight of this call
-	fn weight(&self) -> DispatchInfo;
-}
-
-/// Type callable with ethereum message, may be implemented by [`solidity_interface`] macro
-/// on interface implementation, or for externally-owned real EVM contract
-pub trait Callable<C: Call> {
-	/// Call contract using specified call data
-	fn call(&mut self, call: types::Msg<C>) -> execution::ResultWithPostInfo<AbiWriter>;
-}
-
-/// Implementation of ERC165 is implicitly generated for all interfaces in [`solidity_interface`],
-/// this structure holds parsed data for ERC165Call subvariant
-///
-/// Note: no [`Callable`] implementation is provided, call implementation is inlined into every
-/// implementing contract
-///
-/// See <https://eips.ethereum.org/EIPS/eip-165>
-#[derive(Debug)]
-pub enum ERC165Call {
-	/// ERC165 provides single method, which returns true, if contract
-	/// implements specified interface
-	SupportsInterface {
-		/// Requested interface
-		interface_id: types::Bytes4,
-	},
-}
-
-impl ERC165Call {
-	/// ERC165 selector is provided by standard
-	pub const INTERFACE_ID: types::Bytes4 = u32::to_be_bytes(0x01ffc9a7);
-}
-
-impl Call for ERC165Call {
-	fn parse(selector: types::Bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>> {
-		if selector != Self::INTERFACE_ID {
-			return Ok(None);
-		}
-		Ok(Some(Self::SupportsInterface {
-			interface_id: types::Bytes4::abi_read(input)?,
-		}))
-	}
-}
-
-/// Generate "tests", which will generate solidity code on execution and print it to stdout
-/// Script at .maintain/scripts/generate_api.sh can split this output from test runtime
-///
-/// This macro receives type usage as second argument, but you can use anything as generics,
-/// because no bounds are implied
-#[macro_export]
-macro_rules! generate_stubgen {
-	($name:ident, $decl:ty, $is_impl:literal) => {
-		#[cfg(feature = "stubgen")]
-		#[test]
-		#[ignore]
-		fn $name() {
-			use evm_coder::solidity::TypeCollector;
-			let mut out = TypeCollector::new();
-			<$decl>::generate_solidity_interface(&mut out, $is_impl);
-			println!("=== SNIP START ===");
-			println!("// SPDX-License-Identifier: OTHER");
-			println!("// This code is automatically generated");
-			println!();
-			println!("pragma solidity >=0.8.0 <0.9.0;");
-			println!();
-			for b in out.finish() {
-				println!("{}", b);
-			}
-			println!("=== SNIP END ===");
-		}
-	};
-}
-
-#[cfg(test)]
-mod tests {
-	use super::*;
-
-	#[test]
-	fn function_selector_generation() {
-		assert_eq!(fn_selector!(transfer(address, uint256)), 0xa9059cbb);
-	}
-
-	#[test]
-	fn event_topic_generation() {
-		assert_eq!(
-			hex::encode(&event_topic!(Transfer(address, address, uint256))[..]),
-			"ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
-		);
-	}
-}
deletedcrates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/impls.rs
+++ /dev/null
@@ -1,179 +0,0 @@
-use super::{TypeCollector, SolidityTypeName, SolidityTupleTy};
-use crate::{sealed, types::*};
-use core::fmt;
-use primitive_types::{U256, H160};
-
-macro_rules! solidity_type_name {
-    ($($ty:ty => $name:literal $simple:literal = $default:literal),* $(,)?) => {
-        $(
-            impl SolidityTypeName for $ty {
-                fn solidity_name(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {
-                    write!(writer, $name)
-                }
-				fn is_simple() -> bool {
-					$simple
-				}
-				fn solidity_default(writer: &mut impl core::fmt::Write, _tc: &TypeCollector) -> core::fmt::Result {
-					write!(writer, $default)
-				}
-            }
-        )*
-    };
-}
-
-solidity_type_name! {
-	u8 => "uint8" true = "0",
-	u32 => "uint32" true = "0",
-	u64 => "uint64" true = "0",
-	u128 => "uint128" true = "0",
-	U256 => "uint256" true = "0",
-	Bytes4 => "bytes4" true = "bytes4(0)",
-	H160 => "address" true = "0x0000000000000000000000000000000000000000",
-	String => "string" false = "\"\"",
-	Bytes => "bytes" false = "hex\"\"",
-	bool => "bool" true = "false",
-}
-
-impl SolidityTypeName for () {
-	fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
-		Ok(())
-	}
-	fn is_simple() -> bool {
-		true
-	}
-	fn solidity_default(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
-		Ok(())
-	}
-	fn is_void() -> bool {
-		true
-	}
-}
-
-impl<T: SolidityTypeName + sealed::CanBePlacedInVec> SolidityTypeName for Vec<T> {
-	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		T::solidity_name(writer, tc)?;
-		write!(writer, "[]")
-	}
-	fn is_simple() -> bool {
-		false
-	}
-	fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		write!(writer, "new ")?;
-		T::solidity_name(writer, tc)?;
-		write!(writer, "[](0)")
-	}
-}
-
-macro_rules! count {
-    () => (0usize);
-    ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
-}
-
-macro_rules! impl_tuples {
-	($($ident:ident)+) => {
-		impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleTy for ($($ident,)+) {
-			fn fields(tc: &TypeCollector) -> Vec<String> {
-				let mut collected = Vec::with_capacity(Self::len());
-				$({
-					let mut out = String::new();
-					$ident::solidity_name(&mut out, tc).expect("no fmt error");
-					collected.push(out);
-				})*;
-				collected
-			}
-
-			fn len() -> usize {
-				count!($($ident)*)
-			}
-		}
-		impl<$($ident: SolidityTypeName + 'static),+> SolidityTypeName for ($($ident,)+) {
-			fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-				write!(writer, "{}", tc.collect_tuple::<Self>())
-			}
-			fn is_simple() -> bool {
-				false
-			}
-			#[allow(unused_assignments)]
-			fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-				write!(writer, "{}(", tc.collect_tuple::<Self>())?;
-				let mut first = true;
-				$(
-					if !first {
-						write!(writer, ",")?;
-					} else {
-						first = false;
-					}
-					<$ident>::solidity_default(writer, tc)?;
-				)*
-				write!(writer, ")")
-			}
-		}
-	};
-}
-
-impl_tuples! {A}
-impl_tuples! {A B}
-impl_tuples! {A B C}
-impl_tuples! {A B C D}
-impl_tuples! {A B C D E}
-impl_tuples! {A B C D E F}
-impl_tuples! {A B C D E F G}
-impl_tuples! {A B C D E F G H}
-impl_tuples! {A B C D E F G H I}
-impl_tuples! {A B C D E F G H I J}
-
-//----- impls for Option -----
-impl<T: SolidityTypeName + 'static> SolidityTypeName for Option<T> {
-	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		write!(writer, "{}", tc.collect_struct::<Self>())
-	}
-	fn is_simple() -> bool {
-		false
-	}
-	fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		write!(writer, "{}(", tc.collect_struct::<Self>())?;
-		bool::solidity_default(writer, tc)?;
-		write!(writer, ", ");
-		T::solidity_default(writer, tc)?;
-		write!(writer, ")")
-	}
-}
-
-impl<T: SolidityTypeName> super::SolidityStructTy for Option<T> {
-	fn generate_solidity_interface(tc: &TypeCollector) -> String {
-		let mut solidity_name = "Option".to_string();
-		let mut generic_name = String::new();
-		T::solidity_name(&mut generic_name, tc);
-		solidity_name.push(
-			generic_name
-				.chars()
-				.next()
-				.expect("Generic name is empty")
-				.to_ascii_uppercase(),
-		);
-		solidity_name.push_str(&generic_name[1..]);
-
-		let interface = super::SolidityStruct {
-			docs: &[" Optional value"],
-			name: solidity_name.as_str(),
-			fields: (
-				super::SolidityStructField::<bool> {
-					docs: &[" Shows the status of accessibility of value"],
-					name: "status",
-					ty: ::core::marker::PhantomData,
-				},
-				super::SolidityStructField::<T> {
-					docs: &[" Actual value if `status` is true"],
-					name: "value",
-					ty: ::core::marker::PhantomData,
-				},
-			),
-		};
-
-		let mut out = String::new();
-		let _ = interface.format(&mut out, tc);
-		tc.collect(out);
-
-		solidity_name.to_string()
-	}
-}
deletedcrates/evm-coder/src/solidity/mod.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/mod.rs
+++ /dev/null
@@ -1,515 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Implementation detail of [`crate::solidity_interface`] macro code-generation.
-//! You should not rely on any public item from this module, as it is only intended to be used
-//! by procedural macro, API and output format may be changed at any time.
-//!
-//! Purpose of this module is to receive solidity contract definition in module-specified
-//! format, and then output string, representing interface of this contract in solidity language
-
-mod traits;
-pub use traits::*;
-mod impls;
-
-#[cfg(not(feature = "std"))]
-use alloc::{vec::Vec, collections::BTreeMap, format};
-#[cfg(feature = "std")]
-use std::collections::BTreeMap;
-use core::{
-	fmt::{self, Write},
-	marker::PhantomData,
-	cell::{Cell, RefCell},
-	cmp::Reverse,
-};
-use impl_trait_for_tuples::impl_for_tuples;
-use crate::{types::*, custom_signature::SignatureUnit};
-
-#[derive(Default)]
-pub struct TypeCollector {
-	/// Code => id
-	/// id ordering is required to perform topo-sort on the resulting data
-	structs: RefCell<BTreeMap<String, usize>>,
-	anonymous: RefCell<BTreeMap<Vec<String>, usize>>,
-	// generic: RefCell<BTreeMap<String, usize>>,
-	id: Cell<usize>,
-}
-impl TypeCollector {
-	pub fn new() -> Self {
-		Self::default()
-	}
-	pub fn collect(&self, item: String) {
-		let id = self.next_id();
-		self.structs.borrow_mut().insert(item, id);
-	}
-	pub fn next_id(&self) -> usize {
-		let v = self.id.get();
-		self.id.set(v + 1);
-		v
-	}
-	/// Collect typle, deduplicating it by type, and returning generated name
-	pub fn collect_tuple<T: SolidityTupleTy>(&self) -> String {
-		let names = T::fields(self);
-		if let Some(id) = self.anonymous.borrow().get(&names).cloned() {
-			return format!("Tuple{}", id);
-		}
-		let id = self.next_id();
-		let mut str = String::new();
-		writeln!(str, "/// @dev anonymous struct").unwrap();
-		writeln!(str, "struct Tuple{} {{", id).unwrap();
-		for (i, name) in names.iter().enumerate() {
-			writeln!(str, "\t{} field_{};", name, i).unwrap();
-		}
-		writeln!(str, "}}").unwrap();
-		self.collect(str);
-		self.anonymous.borrow_mut().insert(names, id);
-		format!("Tuple{}", id)
-	}
-	pub fn collect_struct<T: SolidityStructTy>(&self) -> String {
-		T::generate_solidity_interface(self)
-	}
-	pub fn collect_enum<T: SolidityEnumTy>(&self) -> String {
-		T::generate_solidity_interface(self)
-	}
-	pub fn finish(self) -> Vec<String> {
-		let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();
-		data.sort_by_key(|(_, id)| Reverse(*id));
-		data.into_iter().map(|(code, _)| code).collect()
-	}
-}
-#[derive(Default)]
-pub struct UnnamedArgument<T>(PhantomData<*const T>);
-
-impl<T: SolidityTypeName> SolidityArguments for UnnamedArgument<T> {
-	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		if !T::is_void() {
-			T::solidity_name(writer, tc)?;
-			if !T::is_simple() {
-				write!(writer, " memory")?;
-			}
-			Ok(())
-		} else {
-			Ok(())
-		}
-	}
-	fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result {
-		Ok(())
-	}
-	fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		T::solidity_default(writer, tc)
-	}
-	fn len(&self) -> usize {
-		if T::is_void() {
-			0
-		} else {
-			1
-		}
-	}
-}
-
-pub struct NamedArgument<T>(&'static str, PhantomData<*const T>);
-
-impl<T> NamedArgument<T> {
-	pub fn new(name: &'static str) -> Self {
-		Self(name, Default::default())
-	}
-}
-
-impl<T: SolidityTypeName> SolidityArguments for NamedArgument<T> {
-	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		if !T::is_void() {
-			T::solidity_name(writer, tc)?;
-			if !T::is_simple() {
-				write!(writer, " memory")?;
-			}
-			write!(writer, " {}", self.0)
-		} else {
-			Ok(())
-		}
-	}
-	fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {
-		writeln!(writer, "\t{prefix}\t{};", self.0)
-	}
-	fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		T::solidity_default(writer, tc)
-	}
-	fn len(&self) -> usize {
-		if T::is_void() {
-			0
-		} else {
-			1
-		}
-	}
-}
-
-pub struct SolidityEventArgument<T>(pub bool, &'static str, PhantomData<*const T>);
-
-impl<T> SolidityEventArgument<T> {
-	pub fn new(indexed: bool, name: &'static str) -> Self {
-		Self(indexed, name, Default::default())
-	}
-}
-
-impl<T: SolidityTypeName> SolidityArguments for SolidityEventArgument<T> {
-	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		if !T::is_void() {
-			T::solidity_name(writer, tc)?;
-			if self.0 {
-				write!(writer, " indexed")?;
-			}
-			write!(writer, " {}", self.1)
-		} else {
-			Ok(())
-		}
-	}
-	fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {
-		writeln!(writer, "\t{prefix}\t{};", self.1)
-	}
-	fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		T::solidity_default(writer, tc)
-	}
-	fn len(&self) -> usize {
-		if T::is_void() {
-			0
-		} else {
-			1
-		}
-	}
-}
-
-impl SolidityArguments for () {
-	fn solidity_name(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
-		Ok(())
-	}
-	fn solidity_get(&self, _prefix: &str, _writer: &mut impl fmt::Write) -> fmt::Result {
-		Ok(())
-	}
-	fn solidity_default(&self, _writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
-		Ok(())
-	}
-	fn len(&self) -> usize {
-		0
-	}
-}
-
-#[impl_for_tuples(1, 12)]
-impl SolidityArguments for Tuple {
-	for_tuples!( where #( Tuple: SolidityArguments ),* );
-
-	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		let mut first = true;
-		for_tuples!( #(
-            if !Tuple.is_empty() {
-                if !first {
-                    write!(writer, ", ")?;
-                }
-                first = false;
-                Tuple.solidity_name(writer, tc)?;
-            }
-        )* );
-		Ok(())
-	}
-	fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result {
-		for_tuples!( #(
-            Tuple.solidity_get(prefix, writer)?;
-        )* );
-		Ok(())
-	}
-	fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		if self.is_empty() {
-			Ok(())
-		} else if self.len() == 1 {
-			for_tuples!( #(
-				Tuple.solidity_default(writer, tc)?;
-			)* );
-			Ok(())
-		} else {
-			write!(writer, "(")?;
-			let mut first = true;
-			for_tuples!( #(
-				if !Tuple.is_empty() {
-					if !first {
-						write!(writer, ", ")?;
-					}
-					first = false;
-					Tuple.solidity_default(writer, tc)?;
-				}
-			)* );
-			write!(writer, ")")?;
-			Ok(())
-		}
-	}
-	fn len(&self) -> usize {
-		for_tuples!( #( Tuple.len() )+* )
-	}
-}
-
-pub enum SolidityMutability {
-	Pure,
-	View,
-	Mutable,
-}
-pub struct SolidityFunction<A, R> {
-	pub docs: &'static [&'static str],
-	pub selector: u32,
-	pub hide: bool,
-	pub custom_signature: SignatureUnit,
-	pub name: &'static str,
-	pub args: A,
-	pub result: R,
-	pub mutability: SolidityMutability,
-	pub is_payable: bool,
-}
-impl<A: SolidityArguments, R: SolidityArguments> SolidityFunctions for SolidityFunction<A, R> {
-	fn solidity_name(
-		&self,
-		is_impl: bool,
-		writer: &mut impl fmt::Write,
-		tc: &TypeCollector,
-	) -> fmt::Result {
-		let hide_comment = self.hide.then_some("// ").unwrap_or("");
-		for doc in self.docs {
-			writeln!(writer, "\t{hide_comment}///{}", doc)?;
-		}
-		writeln!(
-			writer,
-			"\t{hide_comment}/// @dev EVM selector for this function is: 0x{:0>8x},",
-			self.selector
-		)?;
-		writeln!(
-			writer,
-			"\t{hide_comment}///  or in textual repr: {}",
-			self.custom_signature.as_str().expect("bad utf-8")
-		)?;
-		write!(writer, "\t{hide_comment}function {}(", self.name)?;
-		self.args.solidity_name(writer, tc)?;
-		write!(writer, ")")?;
-		if is_impl {
-			write!(writer, " public")?;
-		} else {
-			write!(writer, " external")?;
-		}
-		match &self.mutability {
-			SolidityMutability::Pure => write!(writer, " pure")?,
-			SolidityMutability::View => write!(writer, " view")?,
-			SolidityMutability::Mutable => {}
-		}
-		if self.is_payable {
-			write!(writer, " payable")?;
-		}
-		if !self.result.is_empty() {
-			write!(writer, " returns (")?;
-			self.result.solidity_name(writer, tc)?;
-			write!(writer, ")")?;
-		}
-		if is_impl {
-			writeln!(writer, " {{")?;
-			writeln!(writer, "\t{hide_comment}\trequire(false, stub_error);")?;
-			self.args.solidity_get(hide_comment, writer)?;
-			match &self.mutability {
-				SolidityMutability::Pure => {}
-				SolidityMutability::View => writeln!(writer, "\t{hide_comment}\tdummy;")?,
-				SolidityMutability::Mutable => writeln!(writer, "\t{hide_comment}\tdummy = 0;")?,
-			}
-			if !self.result.is_empty() {
-				write!(writer, "\t{hide_comment}\treturn ")?;
-				self.result.solidity_default(writer, tc)?;
-				writeln!(writer, ";")?;
-			}
-			writeln!(writer, "\t{hide_comment}}}")?;
-		} else {
-			writeln!(writer, ";")?;
-		}
-		if self.hide {
-			writeln!(writer, "// FORMATTING: FORCE NEWLINE")?;
-		}
-		Ok(())
-	}
-}
-
-#[impl_for_tuples(0, 48)]
-impl SolidityFunctions for Tuple {
-	for_tuples!( where #( Tuple: SolidityFunctions ),* );
-
-	fn solidity_name(
-		&self,
-		is_impl: bool,
-		writer: &mut impl fmt::Write,
-		tc: &TypeCollector,
-	) -> fmt::Result {
-		let mut first = false;
-		for_tuples!( #(
-            Tuple.solidity_name(is_impl, writer, tc)?;
-        )* );
-		Ok(())
-	}
-}
-
-pub struct SolidityInterface<F: SolidityFunctions> {
-	pub docs: &'static [&'static str],
-	pub selector: Bytes4,
-	pub name: &'static str,
-	pub is: &'static [&'static str],
-	pub functions: F,
-}
-
-impl<F: SolidityFunctions> SolidityInterface<F> {
-	pub fn format(
-		&self,
-		is_impl: bool,
-		out: &mut impl fmt::Write,
-		tc: &TypeCollector,
-	) -> fmt::Result {
-		const ZERO_BYTES: [u8; 4] = [0; 4];
-		for doc in self.docs {
-			writeln!(out, "///{}", doc)?;
-		}
-		if self.selector != ZERO_BYTES {
-			writeln!(
-				out,
-				"/// @dev the ERC-165 identifier for this interface is 0x{:0>8x}",
-				u32::from_be_bytes(self.selector)
-			)?;
-		}
-		if is_impl {
-			write!(out, "contract ")?;
-		} else {
-			write!(out, "interface ")?;
-		}
-		write!(out, "{}", self.name)?;
-		if !self.is.is_empty() {
-			write!(out, " is")?;
-			for (i, n) in self.is.iter().enumerate() {
-				if i != 0 {
-					write!(out, ",")?;
-				}
-				write!(out, " {}", n)?;
-			}
-		}
-		writeln!(out, " {{")?;
-		self.functions.solidity_name(is_impl, out, tc)?;
-		writeln!(out, "}}")?;
-		Ok(())
-	}
-}
-
-pub struct SolidityEvent<A> {
-	pub name: &'static str,
-	pub args: A,
-}
-
-impl<A: SolidityArguments> SolidityFunctions for SolidityEvent<A> {
-	fn solidity_name(
-		&self,
-		_is_impl: bool,
-		writer: &mut impl fmt::Write,
-		tc: &TypeCollector,
-	) -> fmt::Result {
-		write!(writer, "\tevent {}(", self.name)?;
-		self.args.solidity_name(writer, tc)?;
-		writeln!(writer, ");")
-	}
-}
-
-#[impl_for_tuples(0, 48)]
-impl SolidityItems for Tuple {
-	for_tuples!( where #( Tuple: SolidityItems ),* );
-
-	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		for_tuples!( #(
-            Tuple.solidity_name(writer, tc)?;
-        )* );
-		Ok(())
-	}
-}
-
-pub struct SolidityStructField<T> {
-	pub docs: &'static [&'static str],
-	pub name: &'static str,
-	pub ty: PhantomData<*const T>,
-}
-
-impl<T> SolidityItems for SolidityStructField<T>
-where
-	T: SolidityTypeName,
-{
-	fn solidity_name(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		for doc in self.docs {
-			writeln!(out, "///{}", doc)?;
-		}
-		write!(out, "\t")?;
-		T::solidity_name(out, tc)?;
-		writeln!(out, " {};", self.name)?;
-		Ok(())
-	}
-}
-pub struct SolidityStruct<'a, F> {
-	pub docs: &'a [&'a str],
-	// pub generics:
-	pub name: &'a str,
-	pub fields: F,
-}
-impl<F> SolidityStruct<'_, F>
-where
-	F: SolidityItems,
-{
-	pub fn format(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		for doc in self.docs {
-			writeln!(out, "///{}", doc)?;
-		}
-		writeln!(out, "struct {} {{", self.name)?;
-		self.fields.solidity_name(out, tc)?;
-		writeln!(out, "}}")?;
-		Ok(())
-	}
-}
-
-pub struct SolidityEnumVariant {
-	pub docs: &'static [&'static str],
-	pub name: &'static str,
-}
-impl SolidityItems for SolidityEnumVariant {
-	fn solidity_name(&self, out: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
-		for doc in self.docs {
-			writeln!(out, "///{}", doc)?;
-		}
-		write!(out, "\t{}", self.name)?;
-		Ok(())
-	}
-}
-pub struct SolidityEnum {
-	pub docs: &'static [&'static str],
-	pub name: &'static str,
-	pub fields: &'static [SolidityEnumVariant],
-}
-impl SolidityEnum {
-	pub fn format(&self, out: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
-		for doc in self.docs {
-			writeln!(out, "///{}", doc)?;
-		}
-		write!(out, "enum {} {{", self.name)?;
-		for (i, field) in self.fields.iter().enumerate() {
-			if i != 0 {
-				write!(out, ",")?;
-			}
-			writeln!(out)?;
-			field.solidity_name(out, tc)?;
-		}
-		writeln!(out)?;
-		writeln!(out, "}}")?;
-		Ok(())
-	}
-}
deletedcrates/evm-coder/src/solidity/traits.rsdiffbeforeafterboth
--- a/crates/evm-coder/src/solidity/traits.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-use super::TypeCollector;
-use core::fmt;
-
-pub trait SolidityTypeName: 'static {
-	fn solidity_name(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
-	/// "simple" types are stored inline, no `memory` modifier should be used in solidity
-	fn is_simple() -> bool;
-	fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
-	/// Specialization
-	fn is_void() -> bool {
-		false
-	}
-}
-
-pub trait SolidityTupleTy: 'static {
-	fn fields(tc: &TypeCollector) -> Vec<String>;
-	fn len() -> usize;
-}
-pub trait SolidityStructTy: 'static {
-	fn generate_solidity_interface(tc: &TypeCollector) -> String;
-}
-pub trait SolidityEnumTy: 'static {
-	fn generate_solidity_interface(tc: &TypeCollector) -> String;
-	fn solidity_option(&self) -> &str;
-}
-
-pub trait SolidityArguments {
-	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
-	fn solidity_get(&self, prefix: &str, writer: &mut impl fmt::Write) -> fmt::Result;
-	fn solidity_default(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
-	fn is_empty(&self) -> bool {
-		self.len() == 0
-	}
-	fn len(&self) -> usize;
-}
-
-pub trait SolidityFunctions {
-	fn solidity_name(
-		&self,
-		is_impl: bool,
-		writer: &mut impl fmt::Write,
-		tc: &TypeCollector,
-	) -> fmt::Result;
-}
-
-pub trait SolidityItems {
-	fn solidity_name(&self, writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result;
-	// For PhantomData fields
-	// fn is_void()
-}
deletedcrates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/abi_derive_generation.rs
+++ /dev/null
@@ -1,765 +0,0 @@
-mod test_struct {
-	use evm_coder_procedural::AbiCoder;
-	use evm_coder::types::Bytes;
-
-	#[test]
-	fn empty_struct() {
-		let t = trybuild::TestCases::new();
-		t.compile_fail("tests/build_failed/abi_derive_struct_generation.rs");
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct1SimpleParam {
-		_a: u8,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct1DynamicParam {
-		_a: String,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct2SimpleParam {
-		_a: u8,
-		_b: u32,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct2DynamicParam {
-		_a: String,
-		_b: Bytes,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct2MixedParam {
-		_a: u8,
-		_b: Bytes,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct1DerivedSimpleParam {
-		_a: TypeStruct1SimpleParam,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct2DerivedSimpleParam {
-		_a: TypeStruct1SimpleParam,
-		_b: TypeStruct2SimpleParam,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct1DerivedDynamicParam {
-		_a: TypeStruct1DynamicParam,
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct2DerivedDynamicParam {
-		_a: TypeStruct1DynamicParam,
-		_b: TypeStruct2DynamicParam,
-	}
-
-	/// Some docs
-	/// At multi
-	/// line
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct3DerivedMixedParam {
-		/// Docs for A
-		/// multi
-		/// line
-		_a: TypeStruct1SimpleParam,
-		/// Docs for B
-		_b: TypeStruct2DynamicParam,
-		/// Docs for C
-		_c: TypeStruct2MixedParam,
-	}
-
-	#[test]
-	fn impl_abi_type_signature() {
-		assert_eq!(
-			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"(uint8)"
-		);
-		assert_eq!(
-			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"(string)"
-		);
-		assert_eq!(
-			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"(uint8,uint32)"
-		);
-		assert_eq!(
-			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"(string,bytes)"
-		);
-		assert_eq!(
-			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"(uint8,bytes)"
-		);
-		assert_eq!(
-			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"((uint8))"
-		);
-		assert_eq!(
-			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"((uint8),(uint8,uint32))"
-		);
-		assert_eq!(
-			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"((string))"
-		);
-		assert_eq!(
-			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"((string),(string,bytes))"
-		);
-		assert_eq!(
-			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			"((uint8),(string,bytes),(uint8,bytes))"
-		);
-	}
-
-	#[test]
-	fn impl_abi_type_is_dynamic() {
-		assert_eq!(
-			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			false
-		);
-		assert_eq!(
-			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			true
-		);
-		assert_eq!(
-			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			false
-		);
-		assert_eq!(
-			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			true
-		);
-		assert_eq!(
-			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),
-			true
-		);
-		assert_eq!(
-			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			false
-		);
-		assert_eq!(
-			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			false
-		);
-		assert_eq!(
-			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			true
-		);
-		assert_eq!(
-			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			true
-		);
-		assert_eq!(
-			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),
-			true
-		);
-	}
-
-	#[test]
-	fn impl_abi_type_size() {
-		const ABI_ALIGNMENT: usize = 32;
-		assert_eq!(
-			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT
-		);
-		assert_eq!(
-			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT
-		);
-		assert_eq!(
-			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT * 2
-		);
-		assert_eq!(
-			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT * 2
-		);
-		assert_eq!(
-			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT * 2
-		);
-		assert_eq!(
-			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT
-		);
-		assert_eq!(
-			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT * 3
-		);
-		assert_eq!(
-			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT
-		);
-		assert_eq!(
-			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT * 3
-		);
-		assert_eq!(
-			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),
-			ABI_ALIGNMENT * 5
-		);
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct1SimpleParam(u8);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct1DynamicParam(String);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct2SimpleParam(u8, u32);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct2DynamicParam(String, Bytes);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct2MixedParam(u8, Bytes);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct2DerivedSimpleParam(TupleStruct1SimpleParam, TupleStruct2SimpleParam);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam);
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct2DerivedDynamicParam(TupleStruct1DynamicParam, TupleStruct2DynamicParam);
-
-	/// Some docs
-	/// At multi
-	/// line
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct3DerivedMixedParam(
-		/// Docs for A
-		/// multi
-		/// line
-		TupleStruct1SimpleParam,
-		TupleStruct2DynamicParam,
-		/// Docs for C
-		TupleStruct2MixedParam,
-	);
-
-	#[test]
-	fn impl_abi_type_signature_same_for_structs() {
-		assert_eq!(
-			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap()
-		);
-		assert_eq!(
-			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap()
-		);
-		assert_eq!(
-			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap()
-		);
-		assert_eq!(
-			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap()
-		);
-		assert_eq!(
-			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-		);
-		assert_eq!(
-			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-		);
-		assert_eq!(
-			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-		);
-		assert_eq!(
-			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-		);
-		assert_eq!(
-			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-		);
-		assert_eq!(
-			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-		);
-	}
-
-	#[test]
-	fn impl_abi_type_is_dynamic_same_for_structs() {
-		assert_eq!(
-			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-		assert_eq!(
-			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic(),
-			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::is_dynamic()
-		);
-	}
-
-	#[test]
-	fn impl_abi_type_size_same_for_structs() {
-		assert_eq!(
-			<TypeStruct1SimpleParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct1SimpleParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct1DynamicParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct1DynamicParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct2SimpleParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct2SimpleParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct2DynamicParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct2DynamicParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct2MixedParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct2MixedParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct1DerivedSimpleParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct2DerivedSimpleParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct1DerivedDynamicParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct2DerivedDynamicParam as evm_coder::abi::AbiType>::size()
-		);
-		assert_eq!(
-			<TypeStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size(),
-			<TupleStruct3DerivedMixedParam as evm_coder::abi::AbiType>::size()
-		);
-	}
-
-	const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;
-
-	fn test_impl<Tuple, TupleStruct, TypeStruct>(
-		tuple_data: Tuple,
-		tuple_struct_data: TupleStruct,
-		type_struct_data: TypeStruct,
-	) where
-		TypeStruct: evm_coder::abi::AbiWrite
-			+ evm_coder::abi::AbiRead
-			+ std::cmp::PartialEq
-			+ std::fmt::Debug,
-		TupleStruct: evm_coder::abi::AbiWrite
-			+ evm_coder::abi::AbiRead
-			+ std::cmp::PartialEq
-			+ std::fmt::Debug,
-		Tuple: evm_coder::abi::AbiWrite
-			+ evm_coder::abi::AbiRead
-			+ std::cmp::PartialEq
-			+ std::fmt::Debug,
-	{
-		let encoded_type_struct = test_abi_write_impl(&type_struct_data);
-		let encoded_tuple_struct = test_abi_write_impl(&tuple_struct_data);
-		let encoded_tuple = test_abi_write_impl(&tuple_data);
-
-		similar_asserts::assert_eq!(encoded_tuple, encoded_type_struct);
-		similar_asserts::assert_eq!(encoded_tuple, encoded_tuple_struct);
-
-		{
-			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();
-			let restored_struct_data = <TypeStruct>::abi_read(&mut decoder).unwrap();
-			assert_eq!(restored_struct_data, type_struct_data);
-		}
-		{
-			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_tuple).unwrap();
-			let restored_struct_data = <TupleStruct>::abi_read(&mut decoder).unwrap();
-			assert_eq!(restored_struct_data, tuple_struct_data);
-		}
-
-		{
-			let (_, mut decoder) =
-				evm_coder::abi::AbiReader::new_call(&encoded_type_struct).unwrap();
-			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();
-			assert_eq!(restored_tuple_data, tuple_data);
-		}
-		{
-			let (_, mut decoder) =
-				evm_coder::abi::AbiReader::new_call(&encoded_tuple_struct).unwrap();
-			let restored_tuple_data = <Tuple>::abi_read(&mut decoder).unwrap();
-			assert_eq!(restored_tuple_data, tuple_data);
-		}
-	}
-
-	fn test_abi_write_impl<A>(data: &A) -> Vec<u8>
-	where
-		A: evm_coder::abi::AbiWrite
-			+ evm_coder::abi::AbiRead
-			+ std::cmp::PartialEq
-			+ std::fmt::Debug,
-	{
-		let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);
-		data.abi_write(&mut writer);
-		let encoded_tuple = writer.finish();
-		encoded_tuple
-	}
-
-	#[test]
-	fn codec_struct_1_simple() {
-		let _a = 0xff;
-		test_impl::<(u8,), TupleStruct1SimpleParam, TypeStruct1SimpleParam>(
-			(_a,),
-			TupleStruct1SimpleParam(_a),
-			TypeStruct1SimpleParam { _a },
-		);
-	}
-
-	#[test]
-	fn codec_struct_1_dynamic() {
-		let _a: String = "some string".into();
-		test_impl::<(String,), TupleStruct1DynamicParam, TypeStruct1DynamicParam>(
-			(_a.clone(),),
-			TupleStruct1DynamicParam(_a.clone()),
-			TypeStruct1DynamicParam { _a },
-		);
-	}
-
-	#[test]
-	fn codec_struct_1_derived_simple() {
-		let _a: u8 = 0xff;
-		test_impl::<((u8,),), TupleStruct1DerivedSimpleParam, TypeStruct1DerivedSimpleParam>(
-			((_a,),),
-			TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam(_a)),
-			TypeStruct1DerivedSimpleParam {
-				_a: TypeStruct1SimpleParam { _a },
-			},
-		);
-	}
-
-	#[test]
-	fn codec_struct_1_derived_dynamic() {
-		let _a: String = "some string".into();
-		test_impl::<((String,),), TupleStruct1DerivedDynamicParam, TypeStruct1DerivedDynamicParam>(
-			((_a.clone(),),),
-			TupleStruct1DerivedDynamicParam(TupleStruct1DynamicParam(_a.clone())),
-			TypeStruct1DerivedDynamicParam {
-				_a: TypeStruct1DynamicParam { _a },
-			},
-		);
-	}
-
-	#[test]
-	fn codec_struct_2_simple() {
-		let _a = 0xff;
-		let _b = 0xbeefbaba;
-		test_impl::<(u8, u32), TupleStruct2SimpleParam, TypeStruct2SimpleParam>(
-			(_a, _b),
-			TupleStruct2SimpleParam(_a, _b),
-			TypeStruct2SimpleParam { _a, _b },
-		);
-	}
-
-	#[test]
-	fn codec_struct_2_dynamic() {
-		let _a: String = "some string".into();
-		let _b: Bytes = Bytes(vec![0x11, 0x22, 0x33]);
-		test_impl::<(String, Bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(
-			(_a.clone(), _b.clone()),
-			TupleStruct2DynamicParam(_a.clone(), _b.clone()),
-			TypeStruct2DynamicParam { _a, _b },
-		);
-	}
-
-	#[test]
-	fn codec_struct_2_mixed() {
-		let _a: u8 = 0xff;
-		let _b: Bytes = Bytes(vec![0x11, 0x22, 0x33]);
-		test_impl::<(u8, Bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(
-			(_a.clone(), _b.clone()),
-			TupleStruct2MixedParam(_a.clone(), _b.clone()),
-			TypeStruct2MixedParam { _a, _b },
-		);
-	}
-
-	#[test]
-	fn codec_struct_2_derived_simple() {
-		let _a = 0xff;
-		let _b = 0xbeefbaba;
-		test_impl::<
-			((u8,), (u8, u32)),
-			TupleStruct2DerivedSimpleParam,
-			TypeStruct2DerivedSimpleParam,
-		>(
-			((_a,), (_a, _b)),
-			TupleStruct2DerivedSimpleParam(
-				TupleStruct1SimpleParam(_a),
-				TupleStruct2SimpleParam(_a, _b),
-			),
-			TypeStruct2DerivedSimpleParam {
-				_a: TypeStruct1SimpleParam { _a },
-				_b: TypeStruct2SimpleParam { _a, _b },
-			},
-		);
-	}
-
-	#[test]
-	fn codec_struct_2_derived_dynamic() {
-		let _a = "some string".to_string();
-		let _b = Bytes(vec![0x11, 0x22, 0x33]);
-		test_impl::<
-			((String,), (String, Bytes)),
-			TupleStruct2DerivedDynamicParam,
-			TypeStruct2DerivedDynamicParam,
-		>(
-			((_a.clone(),), (_a.clone(), _b.clone())),
-			TupleStruct2DerivedDynamicParam(
-				TupleStruct1DynamicParam(_a.clone()),
-				TupleStruct2DynamicParam(_a.clone(), _b.clone()),
-			),
-			TypeStruct2DerivedDynamicParam {
-				_a: TypeStruct1DynamicParam { _a: _a.clone() },
-				_b: TypeStruct2DynamicParam { _a, _b },
-			},
-		);
-	}
-
-	#[test]
-	fn codec_struct_3_derived_mixed() {
-		let int = 0xff;
-		let by = Bytes(vec![0x11, 0x22, 0x33]);
-		let string = "some string".to_string();
-		test_impl::<
-			((u8,), (String, Bytes), (u8, Bytes)),
-			TupleStruct3DerivedMixedParam,
-			TypeStruct3DerivedMixedParam,
-		>(
-			((int,), (string.clone(), by.clone()), (int, by.clone())),
-			TupleStruct3DerivedMixedParam(
-				TupleStruct1SimpleParam(int),
-				TupleStruct2DynamicParam(string.clone(), by.clone()),
-				TupleStruct2MixedParam(int, by.clone()),
-			),
-			TypeStruct3DerivedMixedParam {
-				_a: TypeStruct1SimpleParam { _a: int },
-				_b: TypeStruct2DynamicParam {
-					_a: string.clone(),
-					_b: by.clone(),
-				},
-				_c: TypeStruct2MixedParam { _a: int, _b: by },
-			},
-		);
-	}
-
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TypeStruct2SimpleStruct1Simple {
-		_a: TypeStruct2SimpleParam,
-		_b: TypeStruct2SimpleParam,
-		_c: u8,
-	}
-	#[derive(AbiCoder, PartialEq, Debug)]
-	struct TupleStruct2SimpleStruct1Simple(TupleStruct2SimpleParam, TupleStruct2SimpleParam, u8);
-
-	#[test]
-	fn codec_struct_2_struct_simple_1_simple() {
-		let _a = 0xff;
-		let _b = 0xbeefbaba;
-		test_impl::<
-			((u8, u32), (u8, u32), u8),
-			TupleStruct2SimpleStruct1Simple,
-			TypeStruct2SimpleStruct1Simple,
-		>(
-			((_a, _b), (_a, _b), _a),
-			TupleStruct2SimpleStruct1Simple(
-				TupleStruct2SimpleParam(_a, _b),
-				TupleStruct2SimpleParam(_a, _b),
-				_a,
-			),
-			TypeStruct2SimpleStruct1Simple {
-				_a: TypeStruct2SimpleParam { _a, _b },
-				_b: TypeStruct2SimpleParam { _a, _b },
-				_c: _a,
-			},
-		);
-	}
-}
-
-mod test_enum {
-	use evm_coder::AbiCoder;
-
-	/// Some docs
-	/// At multi
-	/// line
-	#[derive(AbiCoder, Debug, PartialEq, Default, Clone, Copy)]
-	#[repr(u8)]
-	enum Color {
-		/// Docs for Red
-		/// multi
-		/// line
-		Red,
-		Green,
-		/// Docs for Blue
-		#[default]
-		Blue,
-	}
-
-	#[test]
-	fn empty() {}
-
-	#[test]
-	fn bad_enums() {
-		let t = trybuild::TestCases::new();
-		t.compile_fail("tests/build_failed/abi_derive_enum_generation.rs");
-	}
-
-	#[test]
-	fn impl_abi_type_signature_same_for_structs() {
-		assert_eq!(
-			<Color as evm_coder::abi::AbiType>::SIGNATURE
-				.as_str()
-				.unwrap(),
-			<u8 as evm_coder::abi::AbiType>::SIGNATURE.as_str().unwrap()
-		);
-	}
-
-	#[test]
-	fn impl_abi_type_is_dynamic_same_for_structs() {
-		assert_eq!(
-			<Color as evm_coder::abi::AbiType>::is_dynamic(),
-			<u8 as evm_coder::abi::AbiType>::is_dynamic()
-		);
-	}
-
-	#[test]
-	fn impl_abi_type_size_same_for_structs() {
-		assert_eq!(
-			<Color as evm_coder::abi::AbiType>::size(),
-			<u8 as evm_coder::abi::AbiType>::size()
-		);
-	}
-
-	#[test]
-	fn test_coder() {
-		const FUNCTION_IDENTIFIER: u32 = 0xdeadbeef;
-
-		let encoded_enum = {
-			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);
-			<Color as evm_coder::abi::AbiWrite>::abi_write(&Color::Green, &mut writer);
-			writer.finish()
-		};
-
-		let encoded_u8 = {
-			let mut writer = evm_coder::abi::AbiWriter::new_call(FUNCTION_IDENTIFIER);
-			<u8 as evm_coder::abi::AbiWrite>::abi_write(&(Color::Green as u8), &mut writer);
-			writer.finish()
-		};
-
-		similar_asserts::assert_eq!(encoded_enum, encoded_u8);
-
-		{
-			let (_, mut decoder) = evm_coder::abi::AbiReader::new_call(&encoded_enum).unwrap();
-			let restored_enum_data =
-				<Color as evm_coder::abi::AbiRead>::abi_read(&mut decoder).unwrap();
-			assert_eq!(restored_enum_data, Color::Green);
-		}
-	}
-}
deletedcrates/evm-coder/tests/build_failed/abi_derive_enum_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/abi_derive_enum_generation.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-use evm_coder_procedural::AbiCoder;
-
-#[derive(AbiCoder)]
-enum NonRepr {
-	A,
-	B,
-	C,
-}
-
-#[derive(AbiCoder)]
-#[repr(u32)]
-enum NonReprU8 {
-	A,
-	B,
-	C,
-}
-
-#[derive(AbiCoder)]
-#[repr(u8)]
-enum RustEnum {
-	A(u128),
-	B,
-	C,
-}
-
-#[derive(AbiCoder)]
-#[repr(u8)]
-enum WithExplicit {
-	A = 128,
-	B,
-	C,
-}
-
-fn main() {
-	assert!(false);
-}
deletedcrates/evm-coder/tests/build_failed/abi_derive_enum_generation.stderrdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/abi_derive_enum_generation.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error: Enum is not "repr(u8)"
- --> tests/build_failed/abi_derive_enum_generation.rs:4:6
-  |
-4 | enum NonRepr {
-  |      ^^^^^^^
-
-error: Enum is not "repr(u8)"
-  --> tests/build_failed/abi_derive_enum_generation.rs:11:8
-   |
-11 | #[repr(u32)]
-   |        ^^^
-
-error: Enumeration parameters should not have fields
-  --> tests/build_failed/abi_derive_enum_generation.rs:21:2
-   |
-21 |     A(u128),
-   |     ^
-
-error: Enumeration options should not have an explicit specified value
-  --> tests/build_failed/abi_derive_enum_generation.rs:29:2
-   |
-29 |     A = 128,
-   |     ^
deletedcrates/evm-coder/tests/build_failed/abi_derive_struct_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/abi_derive_struct_generation.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-use evm_coder_procedural::AbiCoder;
-
-#[derive(AbiCoder, PartialEq, Debug)]
-struct EmptyStruct {}
-
-#[derive(AbiCoder, PartialEq, Debug)]
-struct EmptyTupleStruct();
-
-fn main() {
-	assert!(false);
-}
deletedcrates/evm-coder/tests/build_failed/abi_derive_struct_generation.stderrdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/abi_derive_struct_generation.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: Empty structs not supported
- --> tests/build_failed/abi_derive_struct_generation.rs:4:8
-  |
-4 | struct EmptyStruct {}
-  |        ^^^^^^^^^^^
-
-error: Empty structs not supported
- --> tests/build_failed/abi_derive_struct_generation.rs:7:8
-  |
-7 | struct EmptyTupleStruct();
-  |        ^^^^^^^^^^^^^^^^
deletedcrates/evm-coder/tests/build_failed/custom_signature_over_max_size.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-#![allow(dead_code)]
-use std::str::from_utf8;
-
-use evm_coder::{
-	make_signature,
-	custom_signature::{SignatureUnit, SIGNATURE_SIZE_LIMIT},
-};
-
-trait Name {
-	const SIGNATURE: SignatureUnit;
-
-	fn name() -> &'static str {
-		from_utf8(&Self::SIGNATURE.data[..Self::SIGNATURE.len]).expect("bad utf-8")
-	}
-}
-
-impl<T: Name> Name for Vec<T> {
-	const SIGNATURE: SignatureUnit =
-		evm_coder::make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
-}
-
-struct MaxSize();
-impl Name for MaxSize {
-	const SIGNATURE: SignatureUnit = SignatureUnit {
-		data: [b'!'; SIGNATURE_SIZE_LIMIT],
-		len: SIGNATURE_SIZE_LIMIT,
-	};
-}
-
-const NAME: SignatureUnit = <Vec<MaxSize>>::SIGNATURE;
-
-fn main() {
-	assert!(false);
-}
deletedcrates/evm-coder/tests/build_failed/custom_signature_over_max_size.stderrdiffbeforeafterboth
--- a/crates/evm-coder/tests/build_failed/custom_signature_over_max_size.stderr
+++ /dev/null
@@ -1,21 +0,0 @@
-warning: unused import: `make_signature`
- --> tests/build_failed/custom_signature_over_max_size.rs:5:2
-  |
-5 |     make_signature,
-  |     ^^^^^^^^^^^^^^
-  |
-  = note: `#[warn(unused_imports)]` on by default
-
-error[E0080]: evaluation of `<std::vec::Vec<MaxSize> as Name>::SIGNATURE` failed
-  --> tests/build_failed/custom_signature_over_max_size.rs:19:3
-   |
-19 |         evm_coder::make_signature!(new nameof(T::SIGNATURE) fixed("[]"));
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 256 but the index is 256
-   |
-   = note: this error originates in the macro `$crate::make_signature` which comes from the expansion of the macro `evm_coder::make_signature` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0080]: evaluation of constant value failed
-  --> tests/build_failed/custom_signature_over_max_size.rs:30:29
-   |
-30 | const NAME: SignatureUnit = <Vec<MaxSize>>::SIGNATURE;
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
deletedcrates/evm-coder/tests/conditional_is.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/conditional_is.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use evm_coder::{types::*, solidity_interface, execution::Result};
-
-pub struct Contract(bool);
-
-#[solidity_interface(name = A)]
-impl Contract {
-	fn method_a() -> Result<()> {
-		Ok(())
-	}
-}
-
-#[solidity_interface(name = B)]
-impl Contract {
-	fn method_b() -> Result<()> {
-		Ok(())
-	}
-}
-
-#[solidity_interface(name = Contract, is(
-	A(if(this.0)),
-	B(if(!this.0)),
-))]
-impl Contract {}
-
-#[test]
-fn conditional_erc165() {
-	assert!(ContractCall::supports_interface(
-		&Contract(true),
-		ACall::METHOD_A
-	));
-	assert!(!ContractCall::supports_interface(
-		&Contract(false),
-		ACall::METHOD_A
-	));
-
-	assert!(ContractCall::supports_interface(
-		&Contract(false),
-		BCall::METHOD_B
-	));
-	assert!(!ContractCall::supports_interface(
-		&Contract(true),
-		BCall::METHOD_B
-	));
-}
deletedcrates/evm-coder/tests/generics.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/generics.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use std::marker::PhantomData;
-use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};
-use primitive_types::U256;
-
-pub struct Generic<T>(PhantomData<T>);
-
-#[solidity_interface(name = GenericIs)]
-impl<T> Generic<T> {
-	fn test_1(&self) -> Result<U256> {
-		unreachable!()
-	}
-}
-
-#[solidity_interface(name = Generic, is(GenericIs))]
-impl<T: Into<u32>> Generic<T> {
-	fn test_2(&self) -> Result<U256> {
-		unreachable!()
-	}
-}
-
-generate_stubgen!(gen_iface, GenericCall<()>, false);
-
-#[solidity_interface(name = GenericWhere)]
-impl<T> Generic<T>
-where
-	T: core::fmt::Debug,
-{
-	fn test_3(&self) -> Result<U256> {
-		unreachable!()
-	}
-}
-
-generate_stubgen!(gen_where_iface, GenericWhereCall<()>, false);
deletedcrates/evm-coder/tests/log.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/log.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![allow(dead_code)]
-
-use evm_coder::{ToLog, types::*};
-use primitive_types::U256;
-
-#[derive(ToLog)]
-enum ERC721Log {
-	Transfer {
-		#[indexed]
-		from: Address,
-		#[indexed]
-		to: Address,
-		value: U256,
-	},
-	Eee {
-		#[indexed]
-		aaa: Address,
-		bbb: U256,
-	},
-}
deletedcrates/evm-coder/tests/random.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/random.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![allow(dead_code)] // This test only checks that macros is not panicking
-
-use evm_coder::{
-	abi::AbiType, ToLog, execution::Result, solidity_interface, types::*, solidity, weight,
-};
-use primitive_types::U256;
-
-pub struct Impls;
-
-#[solidity_interface(name = OurInterface)]
-impl Impls {
-	fn fn_a(&self, _input: U256) -> Result<bool> {
-		unreachable!()
-	}
-}
-
-#[solidity_interface(name = OurInterface1)]
-impl Impls {
-	fn fn_b(&self, _input: u128) -> Result<u32> {
-		unreachable!()
-	}
-}
-
-#[derive(ToLog)]
-enum OurEvents {
-	Event1 {
-		field1: u32,
-	},
-	Event2 {
-		field1: u32,
-		#[indexed]
-		field2: u32,
-	},
-}
-
-#[solidity_interface(
-	name = OurInterface2,
-	is(OurInterface),
-	inline_is(OurInterface1),
-	events(OurEvents)
-)]
-impl Impls {
-	#[solidity(rename_selector = "fnK")]
-	fn fn_c(&self, _input: u32) -> Result<u8> {
-		unreachable!()
-	}
-	fn fn_d(&self, _value: u32) -> Result<u32> {
-		unreachable!()
-	}
-
-	fn caller_sensitive(&self, _caller: Caller) -> Result<u8> {
-		unreachable!()
-	}
-	fn payable(&mut self, _value: Value) -> Result<u8> {
-		unreachable!()
-	}
-
-	#[weight(*_weight)]
-	fn with_weight(&self, _weight: u64) -> Result<()> {
-		unreachable!()
-	}
-
-	/// Doccoment example
-	fn with_doc(&self) -> Result<()> {
-		unreachable!()
-	}
-}
-
-#[solidity_interface(
-	name = ValidSelector,
-	expect_selector = 0x00000000,
-)]
-impl Impls {}
deletedcrates/evm-coder/tests/solidity_generation.rsdiffbeforeafterboth
--- a/crates/evm-coder/tests/solidity_generation.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use evm_coder::{abi::AbiType, execution::Result, generate_stubgen, solidity_interface, types::*};
-use primitive_types::U256;
-
-pub struct ERC20;
-
-#[solidity_interface(name = ERC20)]
-impl ERC20 {
-	fn decimals(&self) -> Result<u8> {
-		unreachable!()
-	}
-	/// Get balance of specified owner
-	fn balance_of(&self, _owner: Address) -> Result<U256> {
-		unreachable!()
-	}
-	fn transfer(&mut self, _caller: Caller, _to: Address, _value: U256) -> Result<bool> {
-		unreachable!()
-	}
-	fn transfer_from(
-		&mut self,
-		_caller: Caller,
-		_from: Address,
-		_to: Address,
-		_value: U256,
-	) -> Result<bool> {
-		unreachable!()
-	}
-	fn approve(&mut self, _caller: Caller, _spender: Address, _value: U256) -> Result<bool> {
-		unreachable!()
-	}
-	fn allowance(&self, _owner: Address, _spender: Address) -> Result<U256> {
-		unreachable!()
-	}
-}
-
-generate_stubgen!(gen_impl, ERC20Call, true);
-generate_stubgen!(gen_iface, ERC20Call, false);
modifiedcrates/struct-versioning/src/lib.rsdiffbeforeafterboth
--- a/crates/struct-versioning/src/lib.rs
+++ b/crates/struct-versioning/src/lib.rs
@@ -223,7 +223,7 @@
 		};
 		let current_fields = fields
 			.iter()
-			.filter_map(|(ver, field)| ver.exists_on(version).then(|| field));
+			.filter_map(|(ver, field)| ver.exists_on(version).then_some(field));
 
 		let mut doc = Vec::new();
 		if version > attr.first_version {
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -17,12 +17,12 @@
 //! This module contains the implementation of pallet methods for evm.
 
 pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
-use evm_coder::{
+use pallet_evm_coder_substrate::{
 	abi::AbiType,
-	solidity_interface, solidity, ToLog,
+	solidity_interface, ToLog,
 	types::*,
-	execution::{Result, Error},
-	weight,
+	execution::{Result, Error, PreDispatch},
+	frontier_contract,
 };
 use pallet_evm_coder_substrate::dispatch_to_evm;
 use sp_std::{vec, vec::Vec};
@@ -36,6 +36,11 @@
 	Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf, eth, weights::WeightInfo,
 };
 
+frontier_contract! {
+	macro_rules! CollectionHandle_result {...}
+	impl<T: Config> Contract for CollectionHandle<T> {...}
+}
+
 /// Events for ethereum collection helper.
 #[derive(ToLog)]
 pub enum CollectionHelpersEvents {
@@ -83,7 +88,7 @@
 }
 
 /// @title A contract that allows you to work with collections.
-#[solidity_interface(name = Collection)]
+#[solidity_interface(name = Collection, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> CollectionHandle<T>
 where
 	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
@@ -272,7 +277,7 @@
 			None => return Ok(Default::default()),
 		};
 
-		Ok(eth::CrossAddress::from_sub::<T>(&sponsor))
+		Ok(eth::CrossAddress::from_sub::<T>(sponsor))
 	}
 
 	/// Get current collection limits.
@@ -280,11 +285,6 @@
 	/// @return Array of collection limits
 	fn collection_limits(&self) -> Result<Vec<eth::CollectionLimit>> {
 		let limits = &self.collection.limits;
-
-		let convert_value_from_bool = |ob: Option<bool>| match ob {
-			Some(b) => Some(b as u32),
-			None => None,
-		};
 
 		Ok(vec![
 			eth::CollectionLimit::new(
@@ -307,10 +307,12 @@
 						None
 					}
 				})
-				.unwrap_or(eth::CollectionLimit::new(
-					eth::CollectionLimitField::SponsoredDataRateLimit,
-					Default::default(),
-				)),
+				.unwrap_or_else(|| {
+					eth::CollectionLimit::new(
+						eth::CollectionLimitField::SponsoredDataRateLimit,
+						Default::default(),
+					)
+				}),
 			eth::CollectionLimit::new(eth::CollectionLimitField::TokenLimit, limits.token_limit),
 			eth::CollectionLimit::new(
 				eth::CollectionLimitField::SponsorTransferTimeout,
@@ -322,15 +324,15 @@
 			),
 			eth::CollectionLimit::new(
 				eth::CollectionLimitField::OwnerCanTransfer,
-				convert_value_from_bool(limits.owner_can_transfer),
+				limits.owner_can_transfer.map(u32::from),
 			),
 			eth::CollectionLimit::new(
 				eth::CollectionLimitField::OwnerCanDestroy,
-				convert_value_from_bool(limits.owner_can_destroy),
+				limits.owner_can_destroy.map(u32::from),
 			),
 			eth::CollectionLimit::new(
 				eth::CollectionLimitField::TransferEnabled,
-				convert_value_from_bool(limits.transfers_enabled),
+				limits.transfers_enabled.map(u32::from),
 			),
 		])
 	}
@@ -680,7 +682,7 @@
 
 /// Contains static property keys and values.
 pub mod static_property {
-	use evm_coder::{
+	use pallet_evm_coder_substrate::{
 		execution::{Result, Error},
 	};
 	use alloc::format;
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -105,7 +105,9 @@
 		}
 	}
 	/// Converts [`CrossAddress`] to `CrossAccountId`.
-	pub fn into_sub_cross_account<T>(&self) -> evm_coder::execution::Result<T::CrossAccountId>
+	pub fn into_sub_cross_account<T>(
+		&self,
+	) -> pallet_evm_coder_substrate::execution::Result<T::CrossAccountId>
 	where
 		T: pallet_evm::Config,
 		T::AccountId: From<[u8; 32]>,
@@ -130,7 +132,7 @@
 }
 
 impl TryFrom<up_data_structs::Property> for Property {
-	type Error = evm_coder::execution::Error;
+	type Error = pallet_evm_coder_substrate::execution::Error;
 
 	fn try_from(from: up_data_structs::Property) -> Result<Self, Self::Error> {
 		let key = evm_coder::types::String::from_utf8(from.key.into())
@@ -141,7 +143,7 @@
 }
 
 impl TryInto<up_data_structs::Property> for Property {
-	type Error = evm_coder::execution::Error;
+	type Error = pallet_evm_coder_substrate::execution::Error;
 
 	fn try_into(self) -> Result<up_data_structs::Property, Self::Error> {
 		let key = <Vec<u8>>::from(self.key)
@@ -212,7 +214,7 @@
 }
 
 impl TryInto<up_data_structs::CollectionLimits> for CollectionLimit {
-	type Error = evm_coder::execution::Error;
+	type Error = pallet_evm_coder_substrate::execution::Error;
 
 	fn try_into(self) -> Result<up_data_structs::CollectionLimits, Self::Error> {
 		let value = self
@@ -378,7 +380,8 @@
 	/// Convert vector of [`TokenPropertyPermission`] into vector of [`up_data_structs::PropertyKeyPermission`].
 	pub fn into_property_key_permissions(
 		permissions: Vec<TokenPropertyPermission>,
-	) -> evm_coder::execution::Result<Vec<up_data_structs::PropertyKeyPermission>> {
+	) -> pallet_evm_coder_substrate::execution::Result<Vec<up_data_structs::PropertyKeyPermission>>
+	{
 		let mut perms = Vec::new();
 
 		for TokenPropertyPermission { key, permissions } in permissions {
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -192,7 +192,10 @@
 	}
 
 	/// Consume gas for reading.
-	pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {
+	pub fn consume_store_reads(
+		&self,
+		reads: u64,
+	) -> pallet_evm_coder_substrate::execution::Result<()> {
 		self.recorder
 			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(
 				<T as frame_system::Config>::DbWeight::get()
@@ -202,7 +205,10 @@
 	}
 
 	/// Consume gas for writing.
-	pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {
+	pub fn consume_store_writes(
+		&self,
+		writes: u64,
+	) -> pallet_evm_coder_substrate::execution::Result<()> {
 		self.recorder
 			.consume_gas(T::GasWeightMapping::weight_to_gas(Weight::from_ref_time(
 				<T as frame_system::Config>::DbWeight::get()
@@ -216,7 +222,7 @@
 		&self,
 		reads: u64,
 		writes: u64,
-	) -> evm_coder::execution::Result<()> {
+	) -> pallet_evm_coder_substrate::execution::Result<()> {
 		let weight = <T as frame_system::Config>::DbWeight::get();
 		let reads = weight.read.saturating_mul(reads);
 		let writes = weight.read.saturating_mul(writes);
modifiedpallets/evm-coder-substrate/Cargo.tomldiffbeforeafterboth
--- a/pallets/evm-coder-substrate/Cargo.toml
+++ b/pallets/evm-coder-substrate/Cargo.toml
@@ -7,10 +7,11 @@
 [dependencies]
 # Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it.
 codec = { workspace = true, package = "parity-scale-codec" }
-
 scale-info = { workspace = true }
 
 evm-coder = { workspace = true }
+evm-core = { workspace = true }
+
 frame-benchmarking = { workspace = true, optional = true }
 frame-support = { workspace = true }
 frame-system = { workspace = true }
@@ -19,6 +20,9 @@
 sp-std = { workspace = true }
 up-data-structs = { workspace = true }
 
+evm-coder-substrate-procedural = { path = "./procedural" }
+spez = "0.1.1"
+
 [features]
 default = ["std"]
 runtime-benchmarks = ['frame-benchmarking']
addedpallets/evm-coder-substrate/procedural/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-coder-substrate/procedural/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+edition = "2021"
+name = "evm-coder-substrate-procedural"
+version = "0.1.0"
+
+[dependencies]
+proc-macro2 = "1.0"
+quote = "1.0"
+syn = "1.0"
+
+[lib]
+proc-macro = true
addedpallets/evm-coder-substrate/procedural/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-coder-substrate/procedural/src/lib.rs
@@ -0,0 +1,135 @@
+use std::result;
+
+use proc_macro2::{TokenStream, Ident};
+use quote::quote;
+use syn::{
+	Error, DeriveInput, Data, Attribute,
+	parse::{Parse, ParseBuffer},
+	spanned::Spanned,
+	Expr, parenthesized,
+};
+
+type Result<T = TokenStream, E = syn::Error> = result::Result<T, E>;
+
+fn parse_attr<A: Parse, I>(attrs: &[Attribute], ident: I) -> Result<Option<A>>
+where
+	Ident: PartialEq<I>,
+{
+	let attrs = attrs
+		.iter()
+		.filter(|a| a.path.is_ident(&ident))
+		.collect::<Vec<_>>();
+	if attrs.len() > 1 {
+		return Err(Error::new(
+			attrs[1].span(),
+			"this attribute may be specified only once",
+		));
+	} else if attrs.is_empty() {
+		return Ok(None);
+	}
+	let attr = attrs[0];
+
+	let parsed = syn::parse2(attr.tokens.clone())?;
+	Ok(Some(parsed))
+}
+
+struct WeightAttr {
+	handler: Expr,
+}
+impl Parse for WeightAttr {
+	fn parse(input: &ParseBuffer) -> Result<Self> {
+		let expr;
+		parenthesized!(expr in input);
+		let handler = Expr::parse(&expr)?;
+
+		Ok(Self { handler })
+	}
+}
+
+#[proc_macro_derive(PreDispatch, attributes(pre_dispatch, weight))]
+pub fn derive_predispatch(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
+	fn inner(input: DeriveInput) -> Result {
+		let (impl_generics, ty_generics, _where_clause) = input.generics.split_for_impl();
+		let ident = &input.ident;
+		let Data::Enum(data) = &input.data else {
+			return Err(Error::new_spanned(input, "PreDispatch input is enum"))
+		};
+
+		let matching = data
+			.variants
+			.iter()
+			.map(|var| {
+				let name = &var.ident;
+				let handler = match &var.fields {
+					syn::Fields::Named(named) => {
+						if let Some(weight) = parse_attr::<WeightAttr, _>(&var.attrs, "weight")? {
+							let weight = &weight.handler;
+							let fields = named.named.iter().flat_map(|n| &n.ident);
+							quote! {
+								{#(#fields,)*} => {
+									::pallet_evm_coder_substrate::execution::DispatchInfo {
+										weight: ::pallet_evm_coder_substrate::execution::Weight::from(#weight),
+									}
+								}
+							}
+						} else {
+							quote! {
+								{..} => {
+									::pallet_evm_coder_substrate::execution::DispatchInfo {
+										weight: ::pallet_evm_coder_substrate::execution::Weight::zero()
+									}
+								}
+							}
+						}
+					}
+					syn::Fields::Unit => {
+						if let Some(weight) = parse_attr::<WeightAttr, _>(&var.attrs, "weight")? {
+							let weight = &weight.handler;
+							quote! {
+								=> {
+									::pallet_evm_coder_substrate::execution::DispatchInfo {
+										weight: ::pallet_evm_coder_substrate::execution::Weight::from(#weight),
+									}
+								}
+							}
+						} else {
+							quote! {
+								=> {
+									::pallet_evm_coder_substrate::execution::DispatchInfo {
+										weight: ::pallet_evm_coder_substrate::execution::Weight::zero()
+									}
+								}
+							}
+						}
+					}
+					syn::Fields::Unnamed(_) => {
+						quote! {
+							(call, ..) => {
+								call.dispatch_info()
+							}
+						}
+					}
+				};
+				Ok(quote! {
+					Self::#name #handler,
+				})
+			})
+			.collect::<Result>()?;
+
+		Ok(quote! {
+			#[allow(unused_variables)]
+			impl #impl_generics ::pallet_evm_coder_substrate::execution::PreDispatch for #ident #ty_generics where T: crate::Config {
+				fn dispatch_info(&self) -> ::pallet_evm_coder_substrate::execution::DispatchInfo {
+					match self {
+						#matching
+					}
+				}
+			}
+		})
+	}
+	let item = syn::parse_macro_input!(item as DeriveInput);
+	match inner(item) {
+		Ok(o) => o.into(),
+		Err(e) => e.into_compile_error().into(),
+	}
+}
addedpallets/evm-coder-substrate/src/execution.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/evm-coder-substrate/src/execution.rs
@@ -0,0 +1,186 @@
+// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
+// This file is part of Unique Network.
+
+// Unique Network is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// Unique Network is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
+
+//! Contract execution related types
+
+#[cfg(not(feature = "std"))]
+use alloc::string::{String, ToString};
+#[cfg(feature = "std")]
+use std::string::{String, ToString};
+
+use evm_coder::ERC165Call;
+use evm_core::{ExitError, ExitFatal};
+
+pub use frame_support::weights::Weight;
+pub use evm_coder_substrate_procedural::PreDispatch;
+
+/// Execution error, should be convertible between EVM and Substrate.
+#[derive(Debug, Clone)]
+pub enum Error {
+	/// Non-fatal contract error occured
+	Revert(String),
+	/// EVM fatal error
+	Fatal(ExitFatal),
+	/// EVM normal error
+	Error(ExitError),
+}
+
+impl<E> From<E> for Error
+where
+	E: ToString,
+{
+	fn from(e: E) -> Self {
+		Self::Revert(e.to_string())
+	}
+}
+
+/// To be used in [`crate::solidity_interface`] implementation.
+pub type Result<T> = core::result::Result<T, Error>;
+/// Return type of items in [`crate::solidity_interface`] definition
+pub type ResultWithPostInfo<T> =
+	core::result::Result<WithPostDispatchInfo<T>, WithPostDispatchInfo<Error>>;
+
+pub trait PreDispatch {
+	fn dispatch_info(&self) -> DispatchInfo;
+}
+
+impl PreDispatch for ERC165Call {
+	fn dispatch_info(&self) -> DispatchInfo {
+		DispatchInfo {
+			// ERC165 impl should be cheap
+			weight: Weight::from_ref_time(200),
+		}
+	}
+}
+
+/// Static information collected from [`crate::weight`].
+pub struct DispatchInfo {
+	/// Statically predicted call weight
+	pub weight: Weight,
+}
+
+impl From<Weight> for DispatchInfo {
+	fn from(weight: Weight) -> Self {
+		Self { weight }
+	}
+}
+impl From<u64> for DispatchInfo {
+	fn from(weight: u64) -> Self {
+		Self {
+			weight: Weight::from_ref_time(weight),
+		}
+	}
+}
+impl From<()> for DispatchInfo {
+	fn from(_: ()) -> Self {
+		Self {
+			weight: Weight::zero(),
+		}
+	}
+}
+
+/// Weight information that is only available post dispatch.
+/// Note: This can only be used to reduce the weight or fee, not increase it.
+#[derive(Default, Clone)]
+pub struct PostDispatchInfo {
+	/// Actual weight consumed by call
+	pub actual_weight: Option<Weight>,
+}
+
+impl PostDispatchInfo {
+	/// Calculate amount to be returned back to user
+	pub fn calc_unspent(&self, info: &DispatchInfo) -> Weight {
+		info.weight - self.calc_actual_weight(info)
+	}
+
+	/// Calculate actual consumed weight, saturating to weight reported
+	/// pre-dispatch
+	pub fn calc_actual_weight(&self, info: &DispatchInfo) -> Weight {
+		if let Some(actual_weight) = self.actual_weight {
+			actual_weight.min(info.weight)
+		} else {
+			info.weight
+		}
+	}
+}
+
+/// Wrapper for PostDispatchInfo and any user-provided data
+#[derive(Clone)]
+pub struct WithPostDispatchInfo<T> {
+	/// User provided data
+	pub data: T,
+	/// Info known after dispatch
+	pub post_info: PostDispatchInfo,
+}
+
+impl<T> From<T> for WithPostDispatchInfo<T> {
+	fn from(data: T) -> Self {
+		Self {
+			data,
+			post_info: Default::default(),
+		}
+	}
+}
+#[allow(clippy::crate_in_macro_def)]
+#[macro_export]
+macro_rules! frontier_contract {
+	(
+		macro_rules! $res:ident {...}
+		impl$(<$($gen:ident $(: $($(+)? $bound:ty)*)?),+ $(,)?>)? Contract for $ty:ty {...}
+	) => {
+		/// Generate macro to convert function return value into Contract result
+		macro_rules! $res {
+			($i:expr) => {{
+				pallet_evm_coder_substrate::spez! {
+					for res = $i;
+					match<T> ::pallet_evm_coder_substrate::execution::ResultWithPostInfo<T> -> ::pallet_evm_coder_substrate::execution::ResultWithPostInfo<T> {
+						res
+					}
+					match<T> ::pallet_evm_coder_substrate::execution::Result<T> -> ::pallet_evm_coder_substrate::execution::ResultWithPostInfo<T> {
+						res
+							.map(pallet_evm_coder_substrate::execution::WithPostDispatchInfo::from)
+							.map_err(pallet_evm_coder_substrate::execution::WithPostDispatchInfo::from)
+					}
+					match<T> T -> ::pallet_evm_coder_substrate::execution::ResultWithPostInfo<T> {
+						Ok(pallet_evm_coder_substrate::execution::WithPostDispatchInfo::from(res))
+					}
+				}
+			}};
+		}
+		impl $(<$($gen),+>)? $crate::Contract for $ty where T: crate::Config {
+			type Error = ::pallet_evm_coder_substrate::execution::Error;
+			type WithPostInfo<R> = ::pallet_evm_coder_substrate::execution::WithPostDispatchInfo<R>;
+			type Result<R, E> = core::result::Result<R, E>;
+			fn map_post<I, O>(
+				v: Self::WithPostInfo<I>,
+				mapper: impl FnOnce(I) -> O,
+			) -> Self::WithPostInfo<O> {
+				::pallet_evm_coder_substrate::execution::WithPostDispatchInfo {
+					data: mapper(v.data),
+					post_info: v.post_info,
+				}
+			}
+			fn with_default_post<V>(v: V) -> Self::WithPostInfo<V> {
+				::pallet_evm_coder_substrate::execution::WithPostDispatchInfo {
+					data: v,
+					post_info: ::pallet_evm_coder_substrate::execution::PostDispatchInfo {
+						actual_weight: None,
+					},
+				}
+			}
+		}
+	};
+}
modifiedpallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth
--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -16,10 +16,13 @@
 
 #![cfg_attr(not(feature = "std"), no_std)]
 
+extern crate self as pallet_evm_coder_substrate;
+
 #[cfg(not(feature = "std"))]
 extern crate alloc;
 #[cfg(not(feature = "std"))]
 use alloc::format;
+use execution::PreDispatch;
 use frame_support::dispatch::Weight;
 
 use core::marker::PhantomData;
@@ -37,10 +40,14 @@
 use sp_core::H160;
 // #[cfg(feature = "runtime-benchmarks")]
 // pub mod benchmarking;
+pub mod execution;
+pub use evm_coder::*;
 
+#[doc(hidden)]
+pub use spez::spez;
+
 use evm_coder::{
 	abi::{AbiReader, AbiWrite, AbiWriter},
-	execution,
 	types::{Msg, Value},
 };
 
@@ -175,7 +182,7 @@
 		handle: &mut impl PrecompileHandle,
 		result: execution::Result<Option<AbiWriter>>,
 	) -> Option<PrecompileResult> {
-		use evm_coder::execution::Error;
+		use execution::Error;
 		// We ignore error here, as it should not occur, as we have our own bookkeeping of gas
 		let _ = handle.record_cost(self.initial_gas - self.gas_left());
 		Some(match result {
@@ -200,7 +207,7 @@
 }
 
 pub fn dispatch_to_evm<T: Config>(err: DispatchError) -> execution::Error {
-	use evm_coder::execution::Error as ExError;
+	use execution::Error as ExError;
 	match err {
 		DispatchError::Module(ModuleError { index, error, .. })
 			if index
@@ -231,15 +238,14 @@
 }
 
 /// Helper to simplify implementing bridge between evm-coder definitions and pallet-evm
-pub fn call<
+pub fn call<T, C, E, H>(handle: &mut H, mut e: E) -> Option<PrecompileResult>
+where
 	T: Config,
-	C: evm_coder::Call + evm_coder::Weighted,
+	C: evm_coder::Call + PreDispatch,
 	E: evm_coder::Callable<C> + WithRecorder<T>,
 	H: PrecompileHandle,
->(
-	handle: &mut H,
-	mut e: E,
-) -> Option<PrecompileResult> {
+	execution::ResultWithPostInfo<AbiWriter>: From<ResultWithPostInfoOf<E, AbiWriter>>,
+{
 	let result = call_internal(
 		handle.context().caller,
 		&mut e,
@@ -249,16 +255,18 @@
 	e.into_recorder().evm_to_precompile_output(handle, result)
 }
 
-fn call_internal<
-	T: Config,
-	C: evm_coder::Call + evm_coder::Weighted,
-	E: evm_coder::Callable<C> + WithRecorder<T>,
->(
+fn call_internal<T, C, E>(
 	caller: H160,
 	e: &mut E,
 	value: Value,
 	input: &[u8],
-) -> execution::Result<Option<AbiWriter>> {
+) -> execution::Result<Option<AbiWriter>>
+where
+	T: Config,
+	C: evm_coder::Call + PreDispatch,
+	E: Contract + evm_coder::Callable<C> + WithRecorder<T>,
+	execution::ResultWithPostInfo<AbiWriter>: From<ResultWithPostInfoOf<E, AbiWriter>>,
+{
 	let (selector, mut reader) = AbiReader::new_call(input)?;
 	let call = C::parse(selector, &mut reader)?;
 	if call.is_none() {
@@ -267,15 +275,15 @@
 	}
 	let call = call.unwrap();
 
-	let dispatch_info = call.weight();
+	let dispatch_info = call.dispatch_info();
 	e.recorder()
 		.consume_gas(T::GasWeightMapping::weight_to_gas(dispatch_info.weight))?;
 
-	match e.call(Msg {
+	match execution::ResultWithPostInfo::from(e.call(Msg {
 		call,
 		caller,
 		value,
-	}) {
+	})) {
 		Ok(v) => {
 			let unspent = v.post_info.calc_unspent(&dispatch_info);
 			e.recorder()
@@ -290,3 +298,26 @@
 		}
 	}
 }
+
+#[cfg(test)]
+#[allow(dead_code)]
+mod tests {
+	use core::marker::PhantomData;
+
+	use evm_coder::ERC165Call;
+	use frame_support::weights::Weight;
+
+	use crate::execution::PreDispatch;
+
+	#[derive(PreDispatch)]
+	enum ExampleCall<T: super::Config> {
+		ERC165Call(ERC165Call, PhantomData<fn() -> T>),
+		OtherCall(ERC165Call),
+
+		#[weight(Weight::from_ref_time(a + b))]
+		Example {
+			a: u64,
+			b: u64,
+		},
+	}
+}
modifiedpallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth
--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -20,7 +20,6 @@
 use core::marker::PhantomData;
 use evm_coder::{
 	abi::{AbiWriter, AbiType},
-	execution::Result,
 	generate_stubgen, solidity_interface,
 	types::*,
 	ToLog,
@@ -30,7 +29,11 @@
 	ExitRevert, OnCreate, OnMethodCall, PrecompileResult, PrecompileFailure, PrecompileHandle,
 	account::CrossAccountId,
 };
-use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder, dispatch_to_evm};
+use pallet_evm_coder_substrate::{
+	SubstrateRecorder, WithRecorder, dispatch_to_evm,
+	execution::{Result, PreDispatch},
+	frontier_contract,
+};
 use pallet_evm_transaction_payment::CallContext;
 use sp_core::{H160, U256};
 use up_data_structs::SponsorshipState;
@@ -42,6 +45,11 @@
 use up_sponsorship::SponsorshipHandler;
 use sp_std::vec::Vec;
 
+frontier_contract! {
+	macro_rules! ContractHelpers_result {...}
+	impl<T: Config> Contract for ContractHelpers<T> {...}
+}
+
 /// Pallet events.
 #[derive(ToLog)]
 pub enum ContractHelpersEvents {
@@ -84,7 +92,7 @@
 }
 
 /// @title Magic contract, which allows users to reconfigure other contracts
-#[solidity_interface(name = ContractHelpers, events(ContractHelpersEvents))]
+#[solidity_interface(name = ContractHelpers, events(ContractHelpersEvents), enum(derive(PreDispatch)))]
 impl<T: Config> ContractHelpers<T>
 where
 	T::AccountId: AsRef<[u8; 32]>,
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -20,10 +20,7 @@
 use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
 use core::convert::TryInto;
 use evm_coder::AbiCoder;
-use evm_coder::{
-	abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,
-	weight,
-};
+use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};
 use up_data_structs::CollectionMode;
 use pallet_common::{
 	CollectionHandle,
@@ -32,7 +29,11 @@
 };
 use sp_std::vec::Vec;
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};
-use pallet_evm_coder_substrate::{call, dispatch_to_evm};
+use pallet_evm_coder_substrate::{
+	call, dispatch_to_evm,
+	execution::{PreDispatch, Result},
+	frontier_contract,
+};
 use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
 use sp_core::{U256, Get};
 
@@ -41,6 +42,11 @@
 	weights::WeightInfo,
 };
 
+frontier_contract! {
+	macro_rules! FungibleHandle_result {...}
+	impl<T: Config> Contract for FungibleHandle<T> {...}
+}
+
 #[derive(ToLog)]
 pub enum ERC20Events {
 	Transfer {
@@ -65,7 +71,7 @@
 	amount: U256,
 }
 
-#[solidity_interface(name = ERC20, events(ERC20Events), expect_selector = 0x942e8b22)]
+#[solidity_interface(name = ERC20, events(ERC20Events), enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x942e8b22)]
 impl<T: Config> FungibleHandle<T> {
 	fn name(&self) -> Result<String> {
 		Ok(decode_utf16(self.name.iter().copied())
@@ -145,7 +151,7 @@
 	}
 }
 
-#[solidity_interface(name = ERC20Mintable)]
+#[solidity_interface(name = ERC20Mintable, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> FungibleHandle<T> {
 	/// Mint tokens for `to` account.
 	/// @param to account that will receive minted tokens
@@ -158,13 +164,13 @@
 		let budget = self
 			.recorder
 			.weight_calls_budget(<StructureWeight<T>>::find_parent());
-		<Pallet<T>>::create_item(&self, &caller, (to, amount), &budget)
+		<Pallet<T>>::create_item(self, &caller, (to, amount), &budget)
 			.map_err(dispatch_to_evm::<T>)?;
 		Ok(true)
 	}
 }
 
-#[solidity_interface(name = ERC20UniqueExtensions)]
+#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> FungibleHandle<T>
 where
 	T::AccountId: From<[u8; 32]>,
@@ -181,10 +187,10 @@
 	}
 
 	/// @notice A description for the collection.
-	fn description(&self) -> Result<String> {
-		Ok(decode_utf16(self.description.iter().copied())
+	fn description(&self) -> String {
+		decode_utf16(self.description.iter().copied())
 			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
-			.collect::<String>())
+			.collect::<String>()
 	}
 
 	#[weight(<SelfWeightOf<T>>::create_item())]
@@ -278,7 +284,7 @@
 			})
 			.collect::<Result<_>>()?;
 
-		<Pallet<T>>::create_multiple_items(&self, &caller, amounts, &budget)
+		<Pallet<T>>::create_multiple_items(self, &caller, amounts, &budget)
 			.map_err(dispatch_to_evm::<T>)?;
 		Ok(true)
 	}
@@ -330,7 +336,8 @@
 		ERC20Mintable,
 		ERC20UniqueExtensions,
 		Collection(via(common_mut returns CollectionHandle<T>)),
-	)
+	),
+	enum(derive(PreDispatch))
 )]
 impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}
 
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -24,16 +24,16 @@
 	char::{REPLACEMENT_CHARACTER, decode_utf16},
 	convert::TryInto,
 };
-use evm_coder::{
-	abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,
-	weight,
-};
+use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};
 use frame_support::BoundedVec;
 use up_data_structs::{
 	TokenId, PropertyPermission, PropertyKeyPermission, Property, CollectionId, PropertyKey,
 	CollectionPropertiesVec,
 };
-use pallet_evm_coder_substrate::dispatch_to_evm;
+use pallet_evm_coder_substrate::{
+	dispatch_to_evm, frontier_contract,
+	execution::{Result, PreDispatch, Error},
+};
 use sp_std::{vec::Vec, vec};
 use pallet_common::{
 	CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
@@ -50,8 +50,13 @@
 	SelfWeightOf, weights::WeightInfo, TokenProperties,
 };
 
+frontier_contract! {
+	macro_rules! NonfungibleHandle_result {...}
+	impl<T: Config> Contract for NonfungibleHandle<T> {...}
+}
+
 /// @title A contract that allows to set and delete token properties and change token property permissions.
-#[solidity_interface(name = TokenProperties)]
+#[solidity_interface(name = TokenProperties, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> NonfungibleHandle<T> {
 	/// @notice Set permissions for token property.
 	/// @dev Throws error if `msg.sender` is not admin or owner of the collection.
@@ -59,8 +64,8 @@
 	/// @param isMutable Permission to mutate property.
 	/// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
 	/// @param tokenOwner Permission to mutate property by token owner if property is mutable.
+	#[solidity(hide)]
 	#[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]
-	#[solidity(hide)]
 	fn set_token_property_permission(
 		&mut self,
 		caller: Caller,
@@ -293,7 +298,7 @@
 
 /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 /// @dev See https://eips.ethereum.org/EIPS/eip-721
-#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]
+#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> NonfungibleHandle<T>
 where
 	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
@@ -301,14 +306,14 @@
 	/// @notice A descriptive name for a collection of NFTs in this contract
 	/// @dev real implementation of this function lies in `ERC721UniqueExtensions`
 	#[solidity(hide, rename_selector = "name")]
-	fn name_proxy(&self) -> Result<String> {
+	fn name_proxy(&self) -> String {
 		self.name()
 	}
 
 	/// @notice An abbreviated name for NFTs in this contract
 	/// @dev real implementation of this function lies in `ERC721UniqueExtensions`
 	#[solidity(hide, rename_selector = "symbol")]
-	fn symbol_proxy(&self) -> Result<String> {
+	fn symbol_proxy(&self) -> String {
 		self.symbol()
 	}
 
@@ -362,14 +367,14 @@
 
 /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 /// @dev See https://eips.ethereum.org/EIPS/eip-721
-#[solidity_interface(name = ERC721Enumerable, expect_selector = 0x780e9d63)]
+#[solidity_interface(name = ERC721Enumerable, expect_selector = 0x780e9d63, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> NonfungibleHandle<T> {
 	/// @notice Enumerate valid NFTs
 	/// @param index A counter less than `totalSupply()`
 	/// @return The token identifier for the `index`th NFT,
 	///  (sort order not specified)
-	fn token_by_index(&self, index: U256) -> Result<U256> {
-		Ok(index)
+	fn token_by_index(&self, index: U256) -> U256 {
+		index
 	}
 
 	/// @dev Not implemented
@@ -389,7 +394,7 @@
 
 /// @title ERC-721 Non-Fungible Token Standard
 /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
-#[solidity_interface(name = ERC721, events(ERC721Events), expect_selector = 0x80ac58cd)]
+#[solidity_interface(name = ERC721, events(ERC721Events), enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x80ac58cd)]
 impl<T: Config> NonfungibleHandle<T> {
 	/// @notice Count all NFTs assigned to an owner
 	/// @dev NFTs assigned to the zero address are considered invalid, and this
@@ -516,7 +521,7 @@
 }
 
 /// @title ERC721 Token that can be irreversibly burned (destroyed).
-#[solidity_interface(name = ERC721Burnable)]
+#[solidity_interface(name = ERC721Burnable, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> NonfungibleHandle<T> {
 	/// @notice Burns a specific ERC721 token.
 	/// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
@@ -533,7 +538,7 @@
 }
 
 /// @title ERC721 minting logic.
-#[solidity_interface(name = ERC721UniqueMintable)]
+#[solidity_interface(name = ERC721UniqueMintable, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> NonfungibleHandle<T> {
 	/// @notice Function to mint a token.
 	/// @param to The new owner
@@ -698,28 +703,28 @@
 }
 
 /// @title Unique extensions for ERC721.
-#[solidity_interface(name = ERC721UniqueExtensions)]
+#[solidity_interface(name = ERC721UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> NonfungibleHandle<T>
 where
 	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
 {
 	/// @notice A descriptive name for a collection of NFTs in this contract
-	fn name(&self) -> Result<String> {
-		Ok(decode_utf16(self.name.iter().copied())
+	fn name(&self) -> String {
+		decode_utf16(self.name.iter().copied())
 			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
-			.collect::<String>())
+			.collect::<String>()
 	}
 
 	/// @notice An abbreviated name for NFTs in this contract
-	fn symbol(&self) -> Result<String> {
-		Ok(String::from_utf8_lossy(&self.token_prefix).into())
+	fn symbol(&self) -> String {
+		String::from_utf8_lossy(&self.token_prefix).into()
 	}
 
 	/// @notice A description for the collection.
-	fn description(&self) -> Result<String> {
-		Ok(decode_utf16(self.description.iter().copied())
+	fn description(&self) -> String {
+		decode_utf16(self.description.iter().copied())
 			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
-			.collect::<String>())
+			.collect::<String>()
 	}
 
 	/// Returns the owner (in cross format) of the token.
@@ -1035,8 +1040,8 @@
 	}
 
 	/// @notice Returns collection helper contract address
-	fn collection_helper_address(&self) -> Result<Address> {
-		Ok(T::ContractAddress::get())
+	fn collection_helper_address(&self) -> Address {
+		T::ContractAddress::get()
 	}
 }
 
@@ -1051,7 +1056,8 @@
 		ERC721Metadata(if(this.flags.erc721metadata)),
 		Collection(via(common_mut returns CollectionHandle<T>)),
 		TokenProperties,
-	)
+	),
+	enum(derive(PreDispatch)),
 )]
 impl<T: Config> NonfungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}
 
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -25,10 +25,7 @@
 	char::{REPLACEMENT_CHARACTER, decode_utf16},
 	convert::TryInto,
 };
-use evm_coder::{
-	abi::AbiType, ToLog, execution::*, generate_stubgen, solidity, solidity_interface, types::*,
-	weight,
-};
+use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};
 use frame_support::{BoundedBTreeMap, BoundedVec};
 use pallet_common::{
 	CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
@@ -37,7 +34,11 @@
 	eth::{self, TokenUri},
 };
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};
-use pallet_evm_coder_substrate::{call, dispatch_to_evm};
+use pallet_evm_coder_substrate::{
+	call, dispatch_to_evm,
+	execution::{PreDispatch, Result, Error},
+	frontier_contract,
+};
 use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
 use sp_core::{H160, U256, Get};
 use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec};
@@ -51,10 +52,15 @@
 	TokenProperties, TokensMinted, TotalSupply, weights::WeightInfo,
 };
 
+frontier_contract! {
+	macro_rules! RefungibleHandle_result {...}
+	impl<T: Config> Contract for RefungibleHandle<T> {...}
+}
+
 pub const ADDRESS_FOR_PARTIALLY_OWNED_TOKENS: H160 = H160::repeat_byte(0xff);
 
 /// @title A contract that allows to set and delete token properties and change token property permissions.
-#[solidity_interface(name = TokenProperties)]
+#[solidity_interface(name = TokenProperties, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleHandle<T> {
 	/// @notice Set permissions for token property.
 	/// @dev Throws error if `msg.sender` is not admin or owner of the collection.
@@ -62,8 +68,8 @@
 	/// @param isMutable Permission to mutate property.
 	/// @param collectionAdmin Permission to mutate property by collection admin if property is mutable.
 	/// @param tokenOwner Permission to mutate property by token owner if property is mutable.
+	#[solidity(hide)]
 	#[weight(<SelfWeightOf<T>>::set_token_property_permissions(1))]
-	#[solidity(hide)]
 	fn set_token_property_permission(
 		&mut self,
 		caller: Caller,
@@ -290,7 +296,7 @@
 
 /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 /// @dev See https://eips.ethereum.org/EIPS/eip-721
-#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]
+#[solidity_interface(name = ERC721Metadata, enum(derive(PreDispatch)), expect_selector = 0x5b5e139f)]
 impl<T: Config> RefungibleHandle<T>
 where
 	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
@@ -359,14 +365,14 @@
 
 /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 /// @dev See https://eips.ethereum.org/EIPS/eip-721
-#[solidity_interface(name = ERC721Enumerable, expect_selector = 0x780e9d63)]
+#[solidity_interface(name = ERC721Enumerable, enum(derive(PreDispatch)), expect_selector = 0x780e9d63)]
 impl<T: Config> RefungibleHandle<T> {
 	/// @notice Enumerate valid RFTs
 	/// @param index A counter less than `totalSupply()`
 	/// @return The token identifier for the `index`th NFT,
 	///  (sort order not specified)
-	fn token_by_index(&self, index: U256) -> Result<U256> {
-		Ok(index)
+	fn token_by_index(&self, index: U256) -> U256 {
+		index
 	}
 
 	/// Not implemented
@@ -386,7 +392,7 @@
 
 /// @title ERC-721 Non-Fungible Token Standard
 /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
-#[solidity_interface(name = ERC721, events(ERC721Events), expect_selector = 0x80ac58cd)]
+#[solidity_interface(name = ERC721, events(ERC721Events), enum(derive(PreDispatch)), enum_attr(weight), expect_selector = 0x80ac58cd)]
 impl<T: Config> RefungibleHandle<T> {
 	/// @notice Count all RFTs assigned to an owner
 	/// @dev RFTs assigned to the zero address are considered invalid, and this
@@ -547,7 +553,7 @@
 }
 
 /// @title ERC721 Token that can be irreversibly burned (destroyed).
-#[solidity_interface(name = ERC721Burnable)]
+#[solidity_interface(name = ERC721Burnable, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleHandle<T> {
 	/// @notice Burns a specific ERC721 token.
 	/// @dev Throws unless `msg.sender` is the current RFT owner, or an authorized
@@ -567,7 +573,7 @@
 }
 
 /// @title ERC721 minting logic.
-#[solidity_interface(name = ERC721UniqueMintable)]
+#[solidity_interface(name = ERC721UniqueMintable, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleHandle<T> {
 	/// @notice Function to mint a token.
 	/// @param to The new owner
@@ -739,7 +745,7 @@
 }
 
 /// @title Unique extensions for ERC721.
-#[solidity_interface(name = ERC721UniqueExtensions)]
+#[solidity_interface(name = ERC721UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleHandle<T>
 where
 	T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
@@ -1120,7 +1126,8 @@
 		ERC721Metadata(if(this.flags.erc721metadata)),
 		Collection(via(common_mut returns CollectionHandle<T>)),
 		TokenProperties,
-	)
+	),
+	enum(derive(PreDispatch)),
 )]
 impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]> {}
 
modifiedpallets/refungible/src/erc_token.rsdiffbeforeafterboth
--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -24,40 +24,41 @@
 	convert::TryInto,
 	ops::Deref,
 };
-use evm_coder::{
-	abi::AbiType, ToLog, execution::*, generate_stubgen, solidity_interface, solidity, types::*,
-	weight,
-};
+use evm_coder::{abi::AbiType, ToLog, generate_stubgen, solidity_interface, types::*};
 use pallet_common::{
-	CommonWeightInfo,
 	erc::{CommonEvmHandler, PrecompileResult},
 	eth::{collection_id_to_address, CrossAddress},
 };
 use pallet_evm::{account::CrossAccountId, PrecompileHandle};
-use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};
+use pallet_evm_coder_substrate::{
+	call, dispatch_to_evm, WithRecorder, frontier_contract,
+	execution::{Result, PreDispatch},
+};
 use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
 use sp_std::vec::Vec;
 use sp_core::U256;
 use up_data_structs::TokenId;
 
-use crate::{
-	Allowance, Balance, common::CommonWeights, Config, Pallet, RefungibleHandle, SelfWeightOf,
-	TotalSupply, weights::WeightInfo,
-};
+use crate::{Allowance, Balance, Config, Pallet, RefungibleHandle, TotalSupply};
 
 /// Refungible token handle contains information about token's collection and id
 ///
 /// RefungibleTokenHandle doesn't check token's existance upon creation
 pub struct RefungibleTokenHandle<T: Config>(pub RefungibleHandle<T>, pub TokenId);
 
-#[solidity_interface(name = ERC1633)]
+frontier_contract! {
+	macro_rules! RefungibleTokenHandle_result {...}
+	impl<T: Config> Contract for RefungibleTokenHandle<T> {...}
+}
+
+#[solidity_interface(name = ERC1633, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleTokenHandle<T> {
-	fn parent_token(&self) -> Result<Address> {
-		Ok(collection_id_to_address(self.id))
+	fn parent_token(&self) -> Address {
+		collection_id_to_address(self.id)
 	}
 
-	fn parent_token_id(&self) -> Result<U256> {
-		Ok(self.1.into())
+	fn parent_token_id(&self) -> U256 {
+		self.1.into()
 	}
 }
 
@@ -89,18 +90,18 @@
 ///
 /// @dev Implementation of the basic standard token.
 /// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md
-#[solidity_interface(name = ERC20, events(ERC20Events))]
+#[solidity_interface(name = ERC20, events(ERC20Events), enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleTokenHandle<T> {
 	/// @return the name of the token.
-	fn name(&self) -> Result<String> {
-		Ok(decode_utf16(self.name.iter().copied())
+	fn name(&self) -> String {
+		decode_utf16(self.name.iter().copied())
 			.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
-			.collect::<String>())
+			.collect::<String>()
 	}
 
 	/// @return the symbol of the token.
-	fn symbol(&self) -> Result<String> {
-		Ok(String::from_utf8_lossy(&self.token_prefix).into())
+	fn symbol(&self) -> String {
+		String::from_utf8_lossy(&self.token_prefix).into()
 	}
 
 	/// @dev Total number of tokens in existence
@@ -198,7 +199,7 @@
 	}
 }
 
-#[solidity_interface(name = ERC20UniqueExtensions)]
+#[solidity_interface(name = ERC20UniqueExtensions, enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T: Config> RefungibleTokenHandle<T>
 where
 	T::AccountId: From<[u8; 32]>,
@@ -361,7 +362,8 @@
 
 #[solidity_interface(
 	name = UniqueRefungibleToken,
-	is(ERC20, ERC20UniqueExtensions, ERC1633)
+	is(ERC20, ERC20UniqueExtensions, ERC1633),
+	enum(derive(PreDispatch)),
 )]
 impl<T: Config> RefungibleTokenHandle<T> where T::AccountId: From<[u8; 32]> {}
 
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -18,9 +18,7 @@
 
 use core::marker::PhantomData;
 use ethereum as _;
-use evm_coder::{
-	abi::AbiType, execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight,
-};
+use evm_coder::{abi::AbiType, generate_stubgen, solidity_interface, types::*};
 use frame_support::traits::Get;
 use crate::Pallet;
 
@@ -32,7 +30,11 @@
 	Pallet as PalletCommon,
 };
 use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};
-use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};
+use pallet_evm_coder_substrate::{
+	dispatch_to_evm, SubstrateRecorder, WithRecorder,
+	execution::{PreDispatch, Result, Error},
+	frontier_contract,
+};
 use up_data_structs::{
 	CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix,
 	CreateCollectionData,
@@ -43,6 +45,10 @@
 use alloc::format;
 use sp_std::vec::Vec;
 
+frontier_contract! {
+	macro_rules! EvmCollectionHelpers_result {...}
+	impl<T: Config> Contract for EvmCollectionHelpers<T> {...}
+}
 /// See [`CollectionHelpersCall`]
 pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);
 impl<T: Config> WithRecorder<T> for EvmCollectionHelpers<T> {
@@ -135,7 +141,7 @@
 }
 
 /// @title Contract, which allows users to operate with collections
-#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents))]
+#[solidity_interface(name = CollectionHelpers, events(CollectionHelpersEvents), enum(derive(PreDispatch)), enum_attr(weight))]
 impl<T> EvmCollectionHelpers<T>
 where
 	T: Config + pallet_common::Config + pallet_nonfungible::Config + pallet_refungible::Config,
@@ -183,9 +189,9 @@
 	/// @param description Informative description of the collection
 	/// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications
 	/// @return address Address of the newly created collection
-	#[weight(<SelfWeightOf<T>>::create_collection())]
 	#[deprecated(note = "mathod was renamed to `create_nft_collection`, prefer it instead")]
 	#[solidity(hide)]
+	#[weight(<SelfWeightOf<T>>::create_collection())]
 	fn create_nonfungible_collection(
 		&mut self,
 		caller: Caller,
modifiedruntime/tests/Cargo.tomldiffbeforeafterboth
--- a/runtime/tests/Cargo.toml
+++ b/runtime/tests/Cargo.toml
@@ -40,5 +40,5 @@
 parity-scale-codec = { version = "3.2.2", default-features = false, features = ["derive"] }
 scale-info = "*"
 
-evm-coder = { default-features = false, path = "../../crates/evm-coder" }
+evm-coder = { workspace = true }
 up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.37" }