diff --git a/Cargo.lock b/Cargo.lock
index 5f1a5133085d..5b3b1265cd8a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,201 +2,6 @@
 # It is not intended for manual editing.
 version = 3
 
-[[package]]
-name = "actix-codec"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8"
-dependencies = [
- "bitflags 1.3.2",
- "bytes",
- "futures-core",
- "futures-sink",
- "memchr",
- "pin-project-lite",
- "tokio",
- "tokio-util",
- "tracing",
-]
-
-[[package]]
-name = "actix-cors"
-version = "0.6.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b340e9cfa5b08690aae90fb61beb44e9b06f44fe3d0f93781aaa58cfba86245e"
-dependencies = [
- "actix-utils",
- "actix-web",
- "derive_more",
- "futures-util",
- "log",
- "once_cell",
- "smallvec",
-]
-
-[[package]]
-name = "actix-http"
-version = "3.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a92ef85799cba03f76e4f7c10f533e66d87c9a7e7055f3391f09000ad8351bc9"
-dependencies = [
- "actix-codec",
- "actix-rt",
- "actix-service",
- "actix-utils",
- "ahash 0.8.7",
- "base64 0.21.5",
- "bitflags 2.4.1",
- "brotli",
- "bytes",
- "bytestring",
- "derive_more",
- "encoding_rs",
- "flate2",
- "futures-core",
- "h2",
- "http",
- "httparse",
- "httpdate",
- "itoa",
- "language-tags",
- "local-channel",
- "mime",
- "percent-encoding",
- "pin-project-lite",
- "rand 0.8.5",
- "sha1",
- "smallvec",
- "tokio",
- "tokio-util",
- "tracing",
- "zstd 0.12.4",
-]
-
-[[package]]
-name = "actix-macros"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
-dependencies = [
- "quote 1.0.33",
- "syn 2.0.38",
-]
-
-[[package]]
-name = "actix-router"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799"
-dependencies = [
- "bytestring",
- "http",
- "regex",
- "serde",
- "tracing",
-]
-
-[[package]]
-name = "actix-rt"
-version = "2.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d"
-dependencies = [
- "actix-macros",
- "futures-core",
- "tokio",
-]
-
-[[package]]
-name = "actix-server"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4"
-dependencies = [
- "actix-rt",
- "actix-service",
- "actix-utils",
- "futures-core",
- "futures-util",
- "mio",
- "socket2 0.5.5",
- "tokio",
- "tracing",
-]
-
-[[package]]
-name = "actix-service"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a"
-dependencies = [
- "futures-core",
- "paste",
- "pin-project-lite",
-]
-
-[[package]]
-name = "actix-utils"
-version = "3.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
-dependencies = [
- "local-waker",
- "pin-project-lite",
-]
-
-[[package]]
-name = "actix-web"
-version = "4.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e4a5b5e29603ca8c94a77c65cf874718ceb60292c5a5c3e5f4ace041af462b9"
-dependencies = [
- "actix-codec",
- "actix-http",
- "actix-macros",
- "actix-router",
- "actix-rt",
- "actix-server",
- "actix-service",
- "actix-utils",
- "actix-web-codegen",
- "ahash 0.8.7",
- "bytes",
- "bytestring",
- "cfg-if 1.0.0",
- "cookie",
- "derive_more",
- "encoding_rs",
- "futures-core",
- "futures-util",
- "itoa",
- "language-tags",
- "log",
- "mime",
- "once_cell",
- "pin-project-lite",
- "regex",
- "serde",
- "serde_json",
- "serde_urlencoded",
- "smallvec",
- "socket2 0.5.5",
- "time",
- "url",
-]
-
-[[package]]
-name = "actix-web-codegen"
-version = "4.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5"
-dependencies = [
- "actix-router",
- "proc-macro2 1.0.69",
- "quote 1.0.33",
- "syn 2.0.38",
-]
-
 [[package]]
 name = "addchain"
 version = "0.2.0"
@@ -462,8 +267,8 @@ dependencies = [
  "memchr",
  "pin-project-lite",
  "tokio",
- "zstd 0.13.0",
- "zstd-safe 7.0.0",
+ "zstd",
+ "zstd-safe",
 ]
 
 [[package]]
@@ -553,13 +358,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
 dependencies = [
  "async-trait",
- "axum-core",
+ "axum-core 0.3.4",
  "bitflags 1.3.2",
  "bytes",
  "futures-util",
- "http",
- "http-body",
- "hyper",
+ "http 0.2.9",
+ "http-body 0.4.5",
+ "hyper 0.14.27",
  "itoa",
  "matchit",
  "memchr",
@@ -577,6 +382,40 @@ dependencies = [
  "tower-service",
 ]
 
+[[package]]
+name = "axum"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e"
+dependencies = [
+ "async-trait",
+ "axum-core 0.4.3",
+ "bytes",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "http-body-util",
+ "hyper 1.2.0",
+ "hyper-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "rustversion",
+ "serde",
+ "serde_json",
+ "serde_path_to_error",
+ "serde_urlencoded",
+ "sync_wrapper",
+ "tokio",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
 [[package]]
 name = "axum-core"
 version = "0.3.4"
@@ -586,12 +425,33 @@ dependencies = [
  "async-trait",
  "bytes",
  "futures-util",
- "http",
- "http-body",
+ "http 0.2.9",
+ "http-body 0.4.5",
+ "mime",
+ "rustversion",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "http-body-util",
  "mime",
+ "pin-project-lite",
  "rustversion",
+ "sync_wrapper",
  "tower-layer",
  "tower-service",
+ "tracing",
 ]
 
 [[package]]
@@ -999,15 +859,6 @@ version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
 
-[[package]]
-name = "bytestring"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae"
-dependencies = [
- "bytes",
-]
-
 [[package]]
 name = "bzip2-sys"
 version = "0.1.11+1.0.8"
@@ -1436,17 +1287,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
 
-[[package]]
-name = "cookie"
-version = "0.16.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb"
-dependencies = [
- "percent-encoding",
- "time",
- "version_check",
-]
-
 [[package]]
 name = "core-foundation"
 version = "0.9.3"
@@ -2537,7 +2377,7 @@ dependencies = [
  "futures-core",
  "futures-sink",
  "gloo-utils",
- "http",
+ "http 0.2.9",
  "js-sys",
  "pin-project",
  "serde",
@@ -2696,7 +2536,26 @@ dependencies = [
  "futures-core",
  "futures-sink",
  "futures-util",
- "http",
+ "http 0.2.9",
+ "indexmap 2.1.0",
+ "slab",
+ "tokio",
+ "tokio-util",
+ "tracing",
+]
+
+[[package]]
+name = "h2"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31d030e59af851932b72ceebadf4a2b5986dba4c3b99dd2493f8273a0f151943"
+dependencies = [
+ "bytes",
+ "fnv",
+ "futures-core",
+ "futures-sink",
+ "futures-util",
+ "http 1.1.0",
  "indexmap 2.1.0",
  "slab",
  "tokio",
@@ -2780,7 +2639,7 @@ dependencies = [
  "base64 0.21.5",
  "bytes",
  "headers-core",
- "http",
+ "http 0.2.9",
  "httpdate",
  "mime",
  "sha1",
@@ -2792,7 +2651,7 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
 dependencies = [
- "http",
+ "http 0.2.9",
 ]
 
 [[package]]
@@ -2883,6 +2742,17 @@ dependencies = [
  "itoa",
 ]
 
+[[package]]
+name = "http"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
 [[package]]
 name = "http-body"
 version = "0.4.5"
@@ -2890,7 +2760,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
 dependencies = [
  "bytes",
- "http",
+ "http 0.2.9",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "http-body"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
+dependencies = [
+ "bytes",
+ "http 1.1.0",
+]
+
+[[package]]
+name = "http-body-util"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http 1.1.0",
+ "http-body 1.0.0",
  "pin-project-lite",
 ]
 
@@ -2922,9 +2815,9 @@ dependencies = [
  "futures-channel",
  "futures-core",
  "futures-util",
- "h2",
- "http",
- "http-body",
+ "h2 0.3.24",
+ "http 0.2.9",
+ "http-body 0.4.5",
  "httparse",
  "httpdate",
  "itoa",
@@ -2936,6 +2829,26 @@ dependencies = [
  "want",
 ]
 
+[[package]]
+name = "hyper"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
+dependencies = [
+ "bytes",
+ "futures-channel",
+ "futures-util",
+ "h2 0.4.2",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "httparse",
+ "httpdate",
+ "itoa",
+ "pin-project-lite",
+ "smallvec",
+ "tokio",
+]
+
 [[package]]
 name = "hyper-rustls"
 version = "0.24.1"
@@ -2943,8 +2856,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97"
 dependencies = [
  "futures-util",
- "http",
- "hyper",
+ "http 0.2.9",
+ "hyper 0.14.27",
  "log",
  "rustls 0.21.7",
  "rustls-native-certs 0.6.3",
@@ -2959,12 +2872,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
 dependencies = [
  "bytes",
- "hyper",
+ "hyper 0.14.27",
  "native-tls",
  "tokio",
  "tokio-native-tls",
 ]
 
+[[package]]
+name = "hyper-util"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa"
+dependencies = [
+ "bytes",
+ "futures-util",
+ "http 1.1.0",
+ "http-body 1.0.0",
+ "hyper 1.2.0",
+ "pin-project-lite",
+ "socket2 0.5.5",
+ "tokio",
+]
+
 [[package]]
 name = "iai"
 version = "0.1.1"
@@ -3214,7 +3143,7 @@ dependencies = [
  "futures-channel",
  "futures-util",
  "gloo-net",
- "http",
+ "http 0.2.9",
  "jsonrpsee-core",
  "pin-project",
  "rustls-native-certs 0.7.0",
@@ -3241,7 +3170,7 @@ dependencies = [
  "beef",
  "futures-timer",
  "futures-util",
- "hyper",
+ "hyper 0.14.27",
  "jsonrpsee-types",
  "parking_lot",
  "pin-project",
@@ -3263,7 +3192,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78b7de9f3219d95985eb77fd03194d7c1b56c19bce1abfcc9d07462574b15572"
 dependencies = [
  "async-trait",
- "hyper",
+ "hyper 0.14.27",
  "hyper-rustls",
  "jsonrpsee-core",
  "jsonrpsee-types",
@@ -3296,8 +3225,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5cc7c6d1a2c58f6135810284a390d9f823d0f508db74cd914d8237802de80f98"
 dependencies = [
  "futures-util",
- "http",
- "hyper",
+ "http 0.2.9",
+ "hyper 0.14.27",
  "jsonrpsee-core",
  "jsonrpsee-types",
  "pin-project",
@@ -3343,7 +3272,7 @@ version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "073c077471e89c4b511fa88b3df9a0f0abdf4a0a2e6683dd2ab36893af87bb2d"
 dependencies = [
- "http",
+ "http 0.2.9",
  "jsonrpsee-client-transport",
  "jsonrpsee-core",
  "jsonrpsee-types",
@@ -3412,12 +3341,6 @@ dependencies = [
  "zkevm_circuits 1.4.1",
 ]
 
-[[package]]
-name = "language-tags"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
-
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -3563,23 +3486,6 @@ dependencies = [
  "zksync_web3_decl",
 ]
 
-[[package]]
-name = "local-channel"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a493488de5f18c8ffcba89eebb8532ffc562dc400490eb65b84893fae0b178"
-dependencies = [
- "futures-core",
- "futures-sink",
- "local-waker",
-]
-
-[[package]]
-name = "local-waker"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1"
-
 [[package]]
 name = "lock_api"
 version = "0.4.11"
@@ -3746,7 +3652,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a4964177ddfdab1e3a2b37aec7cf320e14169abb0ed73999f558136409178d5"
 dependencies = [
  "base64 0.21.5",
- "hyper",
+ "hyper 0.14.27",
  "indexmap 1.9.3",
  "ipnet",
  "metrics",
@@ -3859,7 +3765,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
 dependencies = [
  "libc",
- "log",
  "wasi 0.11.0+wasi-snapshot-preview1",
  "windows-sys 0.48.0",
 ]
@@ -5161,10 +5066,10 @@ dependencies = [
  "encoding_rs",
  "futures-core",
  "futures-util",
- "h2",
- "http",
- "http-body",
- "hyper",
+ "h2 0.3.24",
+ "http 0.2.9",
+ "http-body 0.4.5",
+ "hyper 0.14.27",
  "hyper-rustls",
  "hyper-tls",
  "ipnet",
@@ -6043,9 +5948,9 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.11.1"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
 dependencies = [
  "serde",
 ]
@@ -6114,7 +6019,7 @@ dependencies = [
  "base64 0.13.1",
  "bytes",
  "futures 0.3.28",
- "http",
+ "http 0.2.9",
  "httparse",
  "log",
  "rand 0.8.5",
@@ -6907,8 +6812,8 @@ dependencies = [
  "bytes",
  "futures-core",
  "futures-util",
- "http",
- "http-body",
+ "http 0.2.9",
+ "http-body 0.4.5",
  "http-range-header",
  "httpdate",
  "iri-string",
@@ -7258,7 +7163,7 @@ name = "vise-exporter"
 version = "0.1.0"
 source = "git+https://github.com/matter-labs/vise.git?rev=1c9cc500e92cf9ea052b230e114a6f9cce4fb2c1#1c9cc500e92cf9ea052b230e114a6f9cce4fb2c1"
 dependencies = [
- "hyper",
+ "hyper 0.14.27",
  "metrics-exporter-prometheus",
  "once_cell",
  "tokio",
@@ -8244,13 +8149,10 @@ dependencies = [
 name = "zksync_core"
 version = "0.1.0"
 dependencies = [
- "actix-cors",
- "actix-rt",
- "actix-web",
  "anyhow",
  "assert_matches",
  "async-trait",
- "axum",
+ "axum 0.6.20",
  "bitflags 1.3.2",
  "chrono",
  "ctrlc",
@@ -8420,9 +8322,8 @@ dependencies = [
 name = "zksync_eth_signer"
 version = "0.1.0"
 dependencies = [
- "actix-rt",
- "actix-web",
  "async-trait",
+ "axum 0.7.4",
  "futures 0.3.28",
  "hex",
  "jsonrpc-core",
@@ -8591,7 +8492,7 @@ dependencies = [
  "flate2",
  "google-cloud-auth",
  "google-cloud-storage",
- "http",
+ "http 0.2.9",
  "prost",
  "serde_json",
  "tempdir",
@@ -8849,32 +8750,13 @@ dependencies = [
  "zksync_types",
 ]
 
-[[package]]
-name = "zstd"
-version = "0.12.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a27595e173641171fc74a1232b7b1c7a7cb6e18222c11e9dfb9888fa424c53c"
-dependencies = [
- "zstd-safe 6.0.6",
-]
-
 [[package]]
 name = "zstd"
 version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
 dependencies = [
- "zstd-safe 7.0.0",
-]
-
-[[package]]
-name = "zstd-safe"
-version = "6.0.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee98ffd0b48ee95e6c5168188e44a54550b1564d9d530ee21d5f0eaed1069581"
-dependencies = [
- "libc",
- "zstd-sys",
+ "zstd-safe",
 ]
 
 [[package]]
diff --git a/core/lib/eth_signer/Cargo.toml b/core/lib/eth_signer/Cargo.toml
index 2da0fbd0a790..ac499bd93363 100644
--- a/core/lib/eth_signer/Cargo.toml
+++ b/core/lib/eth_signer/Cargo.toml
@@ -27,7 +27,6 @@ jsonrpc-core = "18.0.0"
 async-trait = "0.1"
 
 [dev-dependencies]
-actix-rt = "2"
 tokio = { version = "1", features = ["full"] }
-actix-web = "4.0.0-beta.8"
+axum = "0.7"
 futures = "0.3"
diff --git a/core/lib/eth_signer/src/json_rpc_signer.rs b/core/lib/eth_signer/src/json_rpc_signer.rs
index c8c499d40ccd..2e2eaa5caccc 100644
--- a/core/lib/eth_signer/src/json_rpc_signer.rs
+++ b/core/lib/eth_signer/src/json_rpc_signer.rs
@@ -323,10 +323,12 @@ mod messages {
 
 #[cfg(test)]
 mod tests {
-    use actix_web::{
-        post,
-        web::{self, Data},
-        App, HttpResponse, HttpServer, Responder,
+    use std::{future::IntoFuture, sync::Arc};
+
+    use axum::{
+        extract::{Json, State},
+        routing::post,
+        Router,
     };
     use futures::future::{AbortHandle, Abortable};
     use jsonrpc_core::{Failure, Id, Output, Success, Version};
@@ -336,8 +338,10 @@ mod tests {
     use super::messages::JsonRpcRequest;
     use crate::{raw_ethereum_tx::TransactionParameters, EthereumSigner, JsonRpcSigner};
 
-    #[post("/")]
-    async fn index(req: web::Json<JsonRpcRequest>, state: web::Data<State>) -> impl Responder {
+    async fn index(
+        State(state): State<Arc<ServerState>>,
+        Json(req): Json<JsonRpcRequest>,
+    ) -> Json<serde_json::Value> {
         let resp = match req.method.as_str() {
             "eth_accounts" => {
                 let mut addresses = vec![];
@@ -357,7 +361,7 @@ mod tests {
             }
             _ => create_fail(req.method.clone()),
         };
-        HttpResponse::Ok().json(json!(resp))
+        Json(json!(resp))
     }
 
     fn create_fail(method: String) -> Output {
@@ -380,25 +384,21 @@ mod tests {
         })
     }
     #[derive(Clone)]
-    struct State {
+    struct ServerState {
         private_keys: Vec<H256>,
     }
 
-    fn run_server(state: State) -> (String, AbortHandle) {
+    async fn run_server(state: ServerState) -> (String, AbortHandle) {
         let mut url = None;
         let mut server = None;
+        let app = Router::new()
+            .route("/", post(index))
+            .with_state(Arc::new(state));
+
         for i in 9000..9999 {
             let new_url = format!("127.0.0.1:{}", i);
-            // Try to bind to some port, hope that 999 variants will be enough
-            let tmp_state = state.clone();
-            if let Ok(ser) = HttpServer::new(move || {
-                App::new()
-                    .app_data(Data::new(tmp_state.clone()))
-                    .service(index)
-            })
-            .bind(new_url.clone())
-            {
-                server = Some(ser);
+            if let Ok(listener) = tokio::net::TcpListener::bind(&new_url).await {
+                server = Some(axum::serve(listener, app));
                 url = Some(new_url);
                 break;
             }
@@ -406,17 +406,18 @@ mod tests {
 
         let server = server.expect("Could not bind to port from 9000 to 9999");
         let (abort_handle, abort_registration) = AbortHandle::new_pair();
-        let future = Abortable::new(server.run(), abort_registration);
+        let future = Abortable::new(server.into_future(), abort_registration);
         tokio::spawn(future);
         let address = format!("http://{}/", &url.unwrap());
         (address, abort_handle)
     }
 
-    #[actix_rt::test]
+    #[tokio::test]
     async fn run_client() {
-        let (address, abort_handle) = run_server(State {
+        let (address, abort_handle) = run_server(ServerState {
             private_keys: vec![H256::repeat_byte(0x17)],
-        });
+        })
+        .await;
         // Get address is ok,  unlock address is ok, recover address from signature is also ok
         let client = JsonRpcSigner::new(address, None, None).await.unwrap();
 
diff --git a/core/lib/utils/src/lib.rs b/core/lib/utils/src/lib.rs
index 5996f409c919..df26dbf6ab88 100644
--- a/core/lib/utils/src/lib.rs
+++ b/core/lib/utils/src/lib.rs
@@ -5,7 +5,6 @@ mod convert;
 pub mod http_with_retries;
 pub mod misc;
 pub mod panic_extractor;
-pub mod panic_notify;
 mod serde_wrappers;
 pub mod time;
 pub mod wait_for_tasks;
diff --git a/core/lib/utils/src/panic_notify.rs b/core/lib/utils/src/panic_notify.rs
deleted file mode 100644
index 27bd71b5f523..000000000000
--- a/core/lib/utils/src/panic_notify.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Built-in deps
-// External uses
-use futures::{channel::mpsc, executor::block_on, SinkExt, StreamExt};
-use tokio::task::JoinHandle;
-// Local uses
-
-/// If its placed inside thread::spawn closure it will notify channel when this thread panics.
-pub struct ThreadPanicNotify(pub mpsc::Sender<bool>);
-
-impl Drop for ThreadPanicNotify {
-    fn drop(&mut self) {
-        if std::thread::panicking() {
-            block_on(self.0.send(true)).unwrap();
-        }
-    }
-}
-
-pub fn spawn_panic_handler() -> (JoinHandle<anyhow::Result<()>>, mpsc::Sender<bool>) {
-    let (panic_sender, mut panic_receiver) = mpsc::channel(1);
-
-    let handler = tokio::spawn(async move {
-        let _ = panic_receiver.next().await;
-        Ok(())
-    });
-    (handler, panic_sender)
-}
diff --git a/core/lib/zksync_core/Cargo.toml b/core/lib/zksync_core/Cargo.toml
index a7f254c26355..0f88d6925442 100644
--- a/core/lib/zksync_core/Cargo.toml
+++ b/core/lib/zksync_core/Cargo.toml
@@ -90,10 +90,6 @@ axum = { version = "0.6.19", default-features = false, features = [
 ] }
 once_cell = "1.7"
 
-actix-rt = "2.2.0"
-actix-cors = "0.6.0-beta.2"
-actix-web = "4.0.0-beta.8"
-
 tracing = "0.1.26"
 
 [dev-dependencies]
diff --git a/core/lib/zksync_core/src/api_server/contract_verification/api_decl.rs b/core/lib/zksync_core/src/api_server/contract_verification/api_decl.rs
index 7d52970d2282..5e0e4d701ac9 100644
--- a/core/lib/zksync_core/src/api_server/contract_verification/api_decl.rs
+++ b/core/lib/zksync_core/src/api_server/contract_verification/api_decl.rs
@@ -1,4 +1,5 @@
-use actix_web::web;
+use std::sync::Arc;
+
 use zksync_dal::{ConnectionPool, Core};
 
 #[derive(Debug, Clone)]
@@ -18,34 +19,36 @@ impl RestApi {
         }
     }
 
-    /// Creates an actix-web `Scope`, which can be mounted to the HTTP server.
-    pub fn into_scope(self) -> actix_web::Scope {
-        web::scope("")
-            .app_data(web::Data::new(self))
-            .route("/contract_verification", web::post().to(Self::verification))
+    pub fn into_router(self) -> axum::Router<()> {
+        axum::Router::new()
+            .route(
+                "/contract_verification",
+                axum::routing::post(Self::verification),
+            )
             .route(
                 "/contract_verification/zksolc_versions",
-                web::get().to(Self::zksolc_versions),
+                axum::routing::get(Self::zksolc_versions),
             )
             .route(
                 "/contract_verification/solc_versions",
-                web::get().to(Self::solc_versions),
+                axum::routing::get(Self::solc_versions),
             )
             .route(
                 "/contract_verification/zkvyper_versions",
-                web::get().to(Self::zkvyper_versions),
+                axum::routing::get(Self::zkvyper_versions),
             )
             .route(
                 "/contract_verification/vyper_versions",
-                web::get().to(Self::vyper_versions),
+                axum::routing::get(Self::vyper_versions),
             )
             .route(
-                "/contract_verification/{id}",
-                web::get().to(Self::verification_request_status),
+                "/contract_verification/:id",
+                axum::routing::get(Self::verification_request_status),
             )
             .route(
-                "/contract_verification/info/{address}",
-                web::get().to(Self::verification_info),
+                "/contract_verification/info/:address",
+                axum::routing::get(Self::verification_info),
             )
+            .with_state(Arc::new(self))
     }
 }
diff --git a/core/lib/zksync_core/src/api_server/contract_verification/api_impl.rs b/core/lib/zksync_core/src/api_server/contract_verification/api_impl.rs
index 2660888e5c61..b8111e98a1cc 100644
--- a/core/lib/zksync_core/src/api_server/contract_verification/api_impl.rs
+++ b/core/lib/zksync_core/src/api_server/contract_verification/api_impl.rs
@@ -1,6 +1,9 @@
-use actix_web::{
-    web::{self, Json},
-    HttpResponse, Result as ActixResult,
+use std::sync::Arc;
+
+use axum::{
+    extract::{Path, State},
+    response::Response,
+    Json,
 };
 use serde::Serialize;
 use zksync_dal::CoreDal;
@@ -8,17 +11,34 @@ use zksync_types::{contract_verification_api::VerificationIncomingRequest, Addre
 
 use super::{api_decl::RestApi, metrics::METRICS};
 
-fn ok_json(data: impl Serialize) -> ActixResult<HttpResponse> {
-    Ok(HttpResponse::Ok().json(data))
+fn ok_json(data: impl Serialize) -> Response<String> {
+    Response::builder()
+        .status(axum::http::StatusCode::OK)
+        .body(serde_json::to_string(&data).expect("Failed to serialize"))
+        .unwrap()
+}
+
+fn bad_request(message: &str) -> Response<String> {
+    Response::builder()
+        .status(axum::http::StatusCode::BAD_REQUEST)
+        .body(message.to_string())
+        .unwrap()
+}
+
+fn not_found() -> Response<String> {
+    Response::builder()
+        .status(axum::http::StatusCode::NOT_FOUND)
+        .body(String::new())
+        .unwrap()
 }
 
 impl RestApi {
     #[tracing::instrument(skip(query))]
     fn validate_contract_verification_query(
         query: &VerificationIncomingRequest,
-    ) -> Result<(), HttpResponse> {
+    ) -> Result<(), Response<String>> {
         if query.source_code_data.compiler_type() != query.compiler_versions.compiler_type() {
-            return Err(HttpResponse::BadRequest().body("incorrect compiler versions"));
+            return Err(bad_request("incorrect compiler versions"));
         }
 
         Ok(())
@@ -27,12 +47,12 @@ impl RestApi {
     /// Add a contract verification job to the queue if the requested contract wasn't previously verified.
     #[tracing::instrument(skip(self_, request))]
     pub async fn verification(
-        self_: web::Data<Self>,
+        State(self_): State<Arc<Self>>,
         Json(request): Json<VerificationIncomingRequest>,
-    ) -> ActixResult<HttpResponse> {
+    ) -> Response<String> {
         let method_latency = METRICS.call[&"contract_verification"].start();
         if let Err(res) = Self::validate_contract_verification_query(&request) {
-            return Ok(res);
+            return res;
         }
         let mut storage = self_
             .master_connection_pool
@@ -45,9 +65,7 @@ impl RestApi {
             .is_contract_deployed_at_address(request.contract_address)
             .await
         {
-            return Ok(
-                HttpResponse::BadRequest().body("There is no deployed contract on this address")
-            );
+            return bad_request("There is no deployed contract on this address");
         }
 
         let request_id = storage
@@ -62,9 +80,9 @@ impl RestApi {
 
     #[tracing::instrument(skip(self_))]
     pub async fn verification_request_status(
-        self_: web::Data<Self>,
-        id: web::Path<usize>,
-    ) -> ActixResult<HttpResponse> {
+        State(self_): State<Arc<Self>>,
+        id: Path<usize>,
+    ) -> Response<String> {
         let method_latency = METRICS.call[&"contract_verification_request_status"].start();
         let status = self_
             .replica_connection_pool
@@ -79,12 +97,12 @@ impl RestApi {
         method_latency.observe();
         match status {
             Some(status) => ok_json(status),
-            None => Ok(HttpResponse::NotFound().finish()),
+            None => not_found(),
         }
     }
 
     #[tracing::instrument(skip(self_))]
-    pub async fn zksolc_versions(self_: web::Data<Self>) -> ActixResult<HttpResponse> {
+    pub async fn zksolc_versions(State(self_): State<Arc<Self>>) -> Response<String> {
         let method_latency = METRICS.call[&"contract_verification_zksolc_versions"].start();
         let versions = self_
             .replica_connection_pool
@@ -101,7 +119,7 @@ impl RestApi {
     }
 
     #[tracing::instrument(skip(self_))]
-    pub async fn solc_versions(self_: web::Data<Self>) -> ActixResult<HttpResponse> {
+    pub async fn solc_versions(State(self_): State<Arc<Self>>) -> Response<String> {
         let method_latency = METRICS.call[&"contract_verification_solc_versions"].start();
         let versions = self_
             .replica_connection_pool
@@ -118,7 +136,7 @@ impl RestApi {
     }
 
     #[tracing::instrument(skip(self_))]
-    pub async fn zkvyper_versions(self_: web::Data<Self>) -> ActixResult<HttpResponse> {
+    pub async fn zkvyper_versions(State(self_): State<Arc<Self>>) -> Response<String> {
         let method_latency = METRICS.call[&"contract_verification_zkvyper_versions"].start();
         let versions = self_
             .replica_connection_pool
@@ -135,7 +153,7 @@ impl RestApi {
     }
 
     #[tracing::instrument(skip(self_))]
-    pub async fn vyper_versions(self_: web::Data<Self>) -> ActixResult<HttpResponse> {
+    pub async fn vyper_versions(State(self_): State<Arc<Self>>) -> Response<String> {
         let method_latency = METRICS.call[&"contract_verification_vyper_versions"].start();
         let versions = self_
             .replica_connection_pool
@@ -153,9 +171,9 @@ impl RestApi {
 
     #[tracing::instrument(skip(self_))]
     pub async fn verification_info(
-        self_: web::Data<Self>,
-        address: web::Path<Address>,
-    ) -> ActixResult<HttpResponse> {
+        State(self_): State<Arc<Self>>,
+        address: Path<Address>,
+    ) -> Response<String> {
         let method_latency = METRICS.call[&"contract_verification_info"].start();
 
         let info = self_
@@ -171,7 +189,7 @@ impl RestApi {
         method_latency.observe();
         match info {
             Some(info) => ok_json(info),
-            None => Ok(HttpResponse::NotFound().finish()),
+            None => not_found(),
         }
     }
 }
diff --git a/core/lib/zksync_core/src/api_server/contract_verification/mod.rs b/core/lib/zksync_core/src/api_server/contract_verification/mod.rs
index 931f12abb4c9..e1aec3752afa 100644
--- a/core/lib/zksync_core/src/api_server/contract_verification/mod.rs
+++ b/core/lib/zksync_core/src/api_server/contract_verification/mod.rs
@@ -1,11 +1,7 @@
-use std::{net::SocketAddr, time::Duration};
-
-use actix_cors::Cors;
-use actix_web::{dev::Server, web, App, HttpResponse, HttpServer};
-use tokio::{sync::watch, task::JoinHandle};
+use anyhow::Context as _;
+use tokio::sync::watch;
 use zksync_config::configs::api::ContractVerificationApiConfig;
 use zksync_dal::ConnectionPool;
-use zksync_utils::panic_notify::{spawn_panic_handler, ThreadPanicNotify};
 
 use self::api_decl::RestApi;
 
@@ -13,66 +9,25 @@ mod api_decl;
 mod api_impl;
 mod metrics;
 
-fn start_server(api: RestApi, bind_to: SocketAddr) -> Server {
-    HttpServer::new(move || {
-        let api = api.clone();
-        App::new()
-            .wrap(
-                Cors::default()
-                    .send_wildcard()
-                    .max_age(3600)
-                    .allow_any_origin()
-                    .allow_any_header()
-                    .allow_any_method(),
-            )
-            .service(api.into_scope())
-            // Endpoint needed for js `isReachable`
-            .route(
-                "/favicon.ico",
-                web::get().to(|| async { HttpResponse::Ok().finish() }),
-            )
-    })
-    .bind(bind_to)
-    .unwrap()
-    .shutdown_timeout(60)
-    .keep_alive(Duration::from_secs(10))
-    .client_request_timeout(Duration::from_secs(60))
-    .disable_signals()
-    .run()
-}
-
-/// Start HTTP REST API
-pub fn start_server_thread_detached(
+pub async fn start_server(
     master_connection_pool: ConnectionPool<zksync_dal::Core>,
     replica_connection_pool: ConnectionPool<zksync_dal::Core>,
     api_config: ContractVerificationApiConfig,
     mut stop_receiver: watch::Receiver<bool>,
-) -> JoinHandle<anyhow::Result<()>> {
-    let (handler, panic_sender) = spawn_panic_handler();
-
-    std::thread::Builder::new()
-        .name("contract-verification-api".to_string())
-        .spawn(move || {
-            let _panic_sentinel = ThreadPanicNotify(panic_sender.clone());
-
-            actix_rt::System::new().block_on(async move {
-                let bind_address = api_config.bind_addr();
-                let api = RestApi::new(master_connection_pool, replica_connection_pool);
-
-                let server = start_server(api, bind_address);
-                let close_handle = server.handle();
-                actix_rt::spawn(async move {
-                    if stop_receiver.changed().await.is_ok() {
-                        close_handle.stop(true).await;
-                        tracing::info!(
-                            "Stop signal received, contract verification API is shutting down"
-                        );
-                    }
-                });
-                server.await.expect("Contract verification API crashed");
-            });
+) -> anyhow::Result<()> {
+    let bind_address = api_config.bind_addr();
+    let api = RestApi::new(master_connection_pool, replica_connection_pool).into_router();
+
+    axum::Server::bind(&bind_address)
+        .serve(api.into_make_service())
+        .with_graceful_shutdown(async move {
+            if stop_receiver.changed().await.is_err() {
+                tracing::warn!("Stop signal sender for contract verification server was dropped without sending a signal");
+            }
+            tracing::info!("Stop signal received, contract verification server is shutting down");
         })
-        .expect("Failed to spawn thread for REST API");
-
-    handler
+        .await
+        .context("Contract verification handler server failed")?;
+    tracing::info!("Contract verification handler server shut down");
+    Ok(())
 }
diff --git a/core/lib/zksync_core/src/lib.rs b/core/lib/zksync_core/src/lib.rs
index 0250f9c64fc9..e82a921b60f5 100644
--- a/core/lib/zksync_core/src/lib.rs
+++ b/core/lib/zksync_core/src/lib.rs
@@ -538,12 +538,12 @@ pub async fn initialize_components(
         if components.contains(&Component::ContractVerificationApi) {
             let started_at = Instant::now();
             tracing::info!("initializing contract verification REST API");
-            task_futures.push(contract_verification::start_server_thread_detached(
+            task_futures.push(tokio::spawn(contract_verification::start_server(
                 connection_pool.clone(),
                 replica_connection_pool.clone(),
                 api_config.contract_verification.clone(),
                 stop_receiver.clone(),
-            ));
+            )));
             let elapsed = started_at.elapsed();
             APP_METRICS.init_latency[&InitStage::ContractVerificationApi].set(elapsed);
             tracing::info!("initialized contract verification REST API in {elapsed:?}");
diff --git a/core/node/node_framework/examples/main_node.rs b/core/node/node_framework/examples/main_node.rs
index c4015164553c..ad408215167a 100644
--- a/core/node/node_framework/examples/main_node.rs
+++ b/core/node/node_framework/examples/main_node.rs
@@ -25,6 +25,7 @@ use zksync_env_config::FromEnv;
 use zksync_node_framework::{
     implementations::layers::{
         commitment_generator::CommitmentGeneratorLayer,
+        contract_verification_api::ContractVerificationApiLayer,
         eth_sender::EthSenderLayer,
         eth_watch::EthWatchLayer,
         healtcheck_server::HealthCheckLayer,
@@ -292,6 +293,12 @@ impl MainNodeBuilder {
         Ok(self)
     }
 
+    fn add_contract_verification_api_layer(mut self) -> anyhow::Result<Self> {
+        let config = ApiConfig::from_env()?.contract_verification;
+        self.node.add_layer(ContractVerificationApiLayer(config));
+        Ok(self)
+    }
+
     fn build(mut self) -> Result<ZkStackService, ZkStackServiceError> {
         self.node.build()
     }
@@ -326,6 +333,7 @@ fn main() -> anyhow::Result<()> {
         .add_ws_web3_api_layer()?
         .add_house_keeper_layer()?
         .add_commitment_generator_layer()?
+        .add_contract_verification_api_layer()?
         .build()?
         .run()?;
 
diff --git a/core/node/node_framework/src/implementations/layers/contract_verification_api.rs b/core/node/node_framework/src/implementations/layers/contract_verification_api.rs
new file mode 100644
index 000000000000..c13366685fbd
--- /dev/null
+++ b/core/node/node_framework/src/implementations/layers/contract_verification_api.rs
@@ -0,0 +1,62 @@
+use zksync_config::configs::api::ContractVerificationApiConfig;
+use zksync_dal::{ConnectionPool, Core};
+
+use crate::{
+    implementations::resources::pools::{MasterPoolResource, ReplicaPoolResource},
+    service::{ServiceContext, StopReceiver},
+    task::Task,
+    wiring_layer::{WiringError, WiringLayer},
+};
+
+#[derive(Debug)]
+pub struct ContractVerificationApiLayer(pub ContractVerificationApiConfig);
+
+#[async_trait::async_trait]
+impl WiringLayer for ContractVerificationApiLayer {
+    fn layer_name(&self) -> &'static str {
+        "contract_verification_api_layer"
+    }
+
+    async fn wire(self: Box<Self>, mut context: ServiceContext<'_>) -> Result<(), WiringError> {
+        let master_pool = context
+            .get_resource::<MasterPoolResource>()
+            .await?
+            .get()
+            .await?;
+        let replica_pool = context
+            .get_resource::<ReplicaPoolResource>()
+            .await?
+            .get()
+            .await?;
+        context.add_task(Box::new(ContractVerificationApiTask {
+            master_pool,
+            replica_pool,
+            config: self.0,
+        }));
+        Ok(())
+    }
+}
+
+#[derive(Debug)]
+pub struct ContractVerificationApiTask {
+    master_pool: ConnectionPool<Core>,
+    replica_pool: ConnectionPool<Core>,
+    config: ContractVerificationApiConfig,
+}
+
+#[async_trait::async_trait]
+impl Task for ContractVerificationApiTask {
+    fn name(&self) -> &'static str {
+        "contract_verification_api"
+    }
+
+    async fn run(self: Box<Self>, stop_receiver: StopReceiver) -> anyhow::Result<()> {
+        zksync_core::api_server::contract_verification::start_server(
+            self.master_pool,
+            self.replica_pool,
+            self.config,
+            stop_receiver.0,
+        )
+        .await
+    }
+}
diff --git a/core/node/node_framework/src/implementations/layers/mod.rs b/core/node/node_framework/src/implementations/layers/mod.rs
index 10563baff35c..b01405e9a686 100644
--- a/core/node/node_framework/src/implementations/layers/mod.rs
+++ b/core/node/node_framework/src/implementations/layers/mod.rs
@@ -1,4 +1,5 @@
 pub mod commitment_generator;
+pub mod contract_verification_api;
 pub mod eth_sender;
 pub mod eth_watch;
 pub mod healtcheck_server;