From 7a3cabda181a6c891287d35ad1cd85dac84468e3 Mon Sep 17 00:00:00 2001
From: tomg10 <lemures64@gmail.com>
Date: Mon, 19 Aug 2024 17:41:59 +0200
Subject: [PATCH 1/6] gateway nonce management

Signed-off-by: tomg10 <lemures64@gmail.com>
---
 ...cf9654c06dfef57863281601c947830ad448a.json |  8 ++-
 ...98012b034605dfb4c48379844085b71e9e381.json | 22 -------
 ...a75893ee5b1b94b6d0f25f1db5342888a2a30.json | 15 +++++
 ...8ab71005d70f13ed32172e47166f71b3aef80.json | 23 ++++++++
 ...3ce80f9b2b27758651ccfc09df61a4ae8a363.json |  8 ++-
 ...98fa893dbc9654d15753e4a538f021af67b60.json | 20 -------
 ...8f65ff83204ebab2ea31847ae305a098823b0.json |  8 ++-
 ...5ac6758a0a4e367f93a9bd48ec82c51e09755.json |  8 ++-
 ...819150019_add_chain_id_to_eth_txs.down.sql |  1 +
 ...40819150019_add_chain_id_to_eth_txs.up.sql |  1 +
 core/lib/dal/src/eth_sender_dal.rs            | 59 ++++++++++++-------
 core/lib/dal/src/models/storage_eth_tx.rs     |  6 +-
 core/lib/types/src/eth_sender.rs              |  3 +
 core/node/eth_sender/src/eth_tx_aggregator.rs | 20 ++++++-
 core/node/eth_sender/src/tester.rs            |  5 +-
 .../layers/eth_sender/aggregator.rs           | 19 ++++--
 16 files changed, 150 insertions(+), 76 deletions(-)
 delete mode 100644 core/lib/dal/.sqlx/query-254d17b5402c123cca0edd6fcdc98012b034605dfb4c48379844085b71e9e381.json
 create mode 100644 core/lib/dal/.sqlx/query-45372b701c23ce782695f11f846a75893ee5b1b94b6d0f25f1db5342888a2a30.json
 create mode 100644 core/lib/dal/.sqlx/query-4aeb7dcd79000540c03fb12c0608ab71005d70f13ed32172e47166f71b3aef80.json
 delete mode 100644 core/lib/dal/.sqlx/query-93725851350146c6ec253a59af598fa893dbc9654d15753e4a538f021af67b60.json
 create mode 100644 core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.down.sql
 create mode 100644 core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.up.sql

diff --git a/core/lib/dal/.sqlx/query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json b/core/lib/dal/.sqlx/query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json
index cdf425de713b..6a3174958db8 100644
--- a/core/lib/dal/.sqlx/query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json
+++ b/core/lib/dal/.sqlx/query-0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a.json
@@ -77,6 +77,11 @@
         "ordinal": 14,
         "name": "is_gateway",
         "type_info": "Bool"
+      },
+      {
+        "ordinal": 15,
+        "name": "chain_id",
+        "type_info": "Int8"
       }
     ],
     "parameters": {
@@ -106,7 +111,8 @@
       false,
       true,
       true,
-      false
+      false,
+      true
     ]
   },
   "hash": "0fede71ed258790cf70d6d6a32dcf9654c06dfef57863281601c947830ad448a"
diff --git a/core/lib/dal/.sqlx/query-254d17b5402c123cca0edd6fcdc98012b034605dfb4c48379844085b71e9e381.json b/core/lib/dal/.sqlx/query-254d17b5402c123cca0edd6fcdc98012b034605dfb4c48379844085b71e9e381.json
deleted file mode 100644
index 8734598cc6f6..000000000000
--- a/core/lib/dal/.sqlx/query-254d17b5402c123cca0edd6fcdc98012b034605dfb4c48379844085b71e9e381.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-  "db_name": "PostgreSQL",
-  "query": "SELECT nonce FROM eth_txs WHERE from_addr = $1::bytea ORDER BY id DESC LIMIT 1",
-  "describe": {
-    "columns": [
-      {
-        "ordinal": 0,
-        "name": "nonce",
-        "type_info": "Int8"
-      }
-    ],
-    "parameters": {
-      "Left": [
-        "Bytea"
-      ]
-    },
-    "nullable": [
-      false
-    ]
-  },
-  "hash": "254d17b5402c123cca0edd6fcdc98012b034605dfb4c48379844085b71e9e381"
-}
diff --git a/core/lib/dal/.sqlx/query-45372b701c23ce782695f11f846a75893ee5b1b94b6d0f25f1db5342888a2a30.json b/core/lib/dal/.sqlx/query-45372b701c23ce782695f11f846a75893ee5b1b94b6d0f25f1db5342888a2a30.json
new file mode 100644
index 000000000000..0567a415ac16
--- /dev/null
+++ b/core/lib/dal/.sqlx/query-45372b701c23ce782695f11f846a75893ee5b1b94b6d0f25f1db5342888a2a30.json
@@ -0,0 +1,15 @@
+{
+  "db_name": "PostgreSQL",
+  "query": "\n            UPDATE eth_txs\n            SET\n                chain_id = $1\n            WHERE\n                id = $2\n            ",
+  "describe": {
+    "columns": [],
+    "parameters": {
+      "Left": [
+        "Int8",
+        "Int4"
+      ]
+    },
+    "nullable": []
+  },
+  "hash": "45372b701c23ce782695f11f846a75893ee5b1b94b6d0f25f1db5342888a2a30"
+}
diff --git a/core/lib/dal/.sqlx/query-4aeb7dcd79000540c03fb12c0608ab71005d70f13ed32172e47166f71b3aef80.json b/core/lib/dal/.sqlx/query-4aeb7dcd79000540c03fb12c0608ab71005d70f13ed32172e47166f71b3aef80.json
new file mode 100644
index 000000000000..feb8f29855e4
--- /dev/null
+++ b/core/lib/dal/.sqlx/query-4aeb7dcd79000540c03fb12c0608ab71005d70f13ed32172e47166f71b3aef80.json
@@ -0,0 +1,23 @@
+{
+  "db_name": "PostgreSQL",
+  "query": "\n            SELECT\n                nonce\n            FROM\n                eth_txs\n            WHERE\n                from_addr IS NOT DISTINCT FROM $1 -- can't just use equality as NULL != NULL\\\n                AND is_gateway = $2\n            ORDER BY\n                id DESC\n            LIMIT\n                1\n            ",
+  "describe": {
+    "columns": [
+      {
+        "ordinal": 0,
+        "name": "nonce",
+        "type_info": "Int8"
+      }
+    ],
+    "parameters": {
+      "Left": [
+        "Bytea",
+        "Bool"
+      ]
+    },
+    "nullable": [
+      false
+    ]
+  },
+  "hash": "4aeb7dcd79000540c03fb12c0608ab71005d70f13ed32172e47166f71b3aef80"
+}
diff --git a/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json b/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json
index 49578cd67bec..1a3c160cee1b 100644
--- a/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json
+++ b/core/lib/dal/.sqlx/query-6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363.json
@@ -77,6 +77,11 @@
         "ordinal": 14,
         "name": "is_gateway",
         "type_info": "Bool"
+      },
+      {
+        "ordinal": 15,
+        "name": "chain_id",
+        "type_info": "Int8"
       }
     ],
     "parameters": {
@@ -99,7 +104,8 @@
       false,
       true,
       true,
-      false
+      false,
+      true
     ]
   },
   "hash": "6692ff6c0fbb2fc94f5cd2837a43ce80f9b2b27758651ccfc09df61a4ae8a363"
diff --git a/core/lib/dal/.sqlx/query-93725851350146c6ec253a59af598fa893dbc9654d15753e4a538f021af67b60.json b/core/lib/dal/.sqlx/query-93725851350146c6ec253a59af598fa893dbc9654d15753e4a538f021af67b60.json
deleted file mode 100644
index 80788846fe69..000000000000
--- a/core/lib/dal/.sqlx/query-93725851350146c6ec253a59af598fa893dbc9654d15753e4a538f021af67b60.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
-  "db_name": "PostgreSQL",
-  "query": "SELECT nonce FROM eth_txs WHERE from_addr IS NULL ORDER BY id DESC LIMIT 1",
-  "describe": {
-    "columns": [
-      {
-        "ordinal": 0,
-        "name": "nonce",
-        "type_info": "Int8"
-      }
-    ],
-    "parameters": {
-      "Left": []
-    },
-    "nullable": [
-      false
-    ]
-  },
-  "hash": "93725851350146c6ec253a59af598fa893dbc9654d15753e4a538f021af67b60"
-}
diff --git a/core/lib/dal/.sqlx/query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json b/core/lib/dal/.sqlx/query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json
index 28058b9e42a7..272f20e5268a 100644
--- a/core/lib/dal/.sqlx/query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json
+++ b/core/lib/dal/.sqlx/query-a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0.json
@@ -77,6 +77,11 @@
         "ordinal": 14,
         "name": "is_gateway",
         "type_info": "Bool"
+      },
+      {
+        "ordinal": 15,
+        "name": "chain_id",
+        "type_info": "Int8"
       }
     ],
     "parameters": {
@@ -100,7 +105,8 @@
       false,
       true,
       true,
-      false
+      false,
+      true
     ]
   },
   "hash": "a71a87d91dcf0f624dbd64eb8828f65ff83204ebab2ea31847ae305a098823b0"
diff --git a/core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json b/core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json
index fb6ea1d2d3e5..b9783f771a7a 100644
--- a/core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json
+++ b/core/lib/dal/.sqlx/query-eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755.json
@@ -77,6 +77,11 @@
         "ordinal": 14,
         "name": "is_gateway",
         "type_info": "Bool"
+      },
+      {
+        "ordinal": 15,
+        "name": "chain_id",
+        "type_info": "Int8"
       }
     ],
     "parameters": {
@@ -101,7 +106,8 @@
       false,
       true,
       true,
-      false
+      false,
+      true
     ]
   },
   "hash": "eab36591af61369e36e3dab79025ac6758a0a4e367f93a9bd48ec82c51e09755"
diff --git a/core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.down.sql b/core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.down.sql
new file mode 100644
index 000000000000..65fcdc9cfcdf
--- /dev/null
+++ b/core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.down.sql
@@ -0,0 +1 @@
+ALTER TABLE eth_txs DROP COLUMN chain_id;
diff --git a/core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.up.sql b/core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.up.sql
new file mode 100644
index 000000000000..bbcfe41a58c1
--- /dev/null
+++ b/core/lib/dal/migrations/20240819150019_add_chain_id_to_eth_txs.up.sql
@@ -0,0 +1 @@
+ALTER TABLE eth_txs ADD COLUMN chain_id BIGINT;
diff --git a/core/lib/dal/src/eth_sender_dal.rs b/core/lib/dal/src/eth_sender_dal.rs
index eb7e1cd642c1..c76547422d8f 100644
--- a/core/lib/dal/src/eth_sender_dal.rs
+++ b/core/lib/dal/src/eth_sender_dal.rs
@@ -404,6 +404,23 @@ impl EthSenderDal<'_, '_> {
         Ok(())
     }
 
+    pub async fn set_chain_id(&mut self, eth_tx_id: u32, chain_id: u64) -> anyhow::Result<()> {
+        sqlx::query!(
+            r#"
+            UPDATE eth_txs
+            SET
+                chain_id = $1
+            WHERE
+                id = $2
+            "#,
+            eth_tx_id as i32,
+            chain_id as i64,
+        )
+        .execute(self.storage.conn())
+        .await?;
+        Ok(())
+    }
+
     pub async fn get_confirmed_tx_hash_by_eth_tx_id(
         &mut self,
         eth_tx_id: u32,
@@ -610,29 +627,29 @@ impl EthSenderDal<'_, '_> {
     pub async fn get_next_nonce(
         &mut self,
         from_address: Option<Address>,
+        is_gateway: bool,
     ) -> sqlx::Result<Option<u64>> {
-        struct NonceRow {
-            nonce: i64,
-        }
-
-        let query = match_query_as!(
-            NonceRow,
-            [
-                "SELECT nonce FROM eth_txs WHERE ",
-                _, // WHERE condition
-                " ORDER BY id DESC LIMIT 1"
-            ],
-            match (from_address) {
-                Some(address) => ("from_addr = $1::bytea"; address.as_bytes()),
-                None => ("from_addr IS NULL";),
-            }
-        );
+        let nonce = sqlx::query!(
+            r#"
+            SELECT
+                nonce
+            FROM
+                eth_txs
+            WHERE
+                from_addr IS NOT DISTINCT FROM $1 -- can't just use equality as NULL != NULL\
+                AND is_gateway = $2
+            ORDER BY
+                id DESC
+            LIMIT
+                1
+            "#,
+            from_address.as_ref().map(|h160| h160.as_bytes()),
+            is_gateway
+        )
+        .fetch_optional(self.storage.conn())
+        .await?;
 
-        let nonce = query
-            .fetch_optional(self.storage.conn())
-            .await?
-            .map(|row| row.nonce as u64);
-        Ok(nonce.map(|n| n + 1))
+        Ok(nonce.map(|row| row.nonce as u64 + 1))
     }
 
     pub async fn mark_failed_transaction(&mut self, eth_tx_id: u32) -> sqlx::Result<()> {
diff --git a/core/lib/dal/src/models/storage_eth_tx.rs b/core/lib/dal/src/models/storage_eth_tx.rs
index c721f938838e..a47f6acfff46 100644
--- a/core/lib/dal/src/models/storage_eth_tx.rs
+++ b/core/lib/dal/src/models/storage_eth_tx.rs
@@ -4,7 +4,7 @@ use sqlx::types::chrono::NaiveDateTime;
 use zksync_types::{
     aggregated_operations::AggregatedActionType,
     eth_sender::{EthTx, TxHistory, TxHistoryToSend},
-    Address, L1BatchNumber, Nonce, H256,
+    Address, L1BatchNumber, Nonce, SLChainId, H256,
 };
 
 #[derive(Debug, Clone)]
@@ -30,6 +30,7 @@ pub struct StorageEthTx {
     // Format a `bincode`-encoded `EthTxBlobSidecar` enum.
     pub blob_sidecar: Option<Vec<u8>>,
     pub is_gateway: bool,
+    pub chain_id: Option<i64>,
 }
 
 #[derive(Debug, Default)]
@@ -85,6 +86,9 @@ impl From<StorageEthTx> for EthTx {
                 bincode::deserialize(&b).expect("EthTxBlobSidecar is encoded correctly; qed")
             }),
             is_gateway: tx.is_gateway,
+            chain_id: tx
+                .chain_id
+                .map(|chain_id| SLChainId(chain_id.try_into().unwrap())),
         }
     }
 }
diff --git a/core/lib/types/src/eth_sender.rs b/core/lib/types/src/eth_sender.rs
index 09ea915283eb..12a5a5a8fb13 100644
--- a/core/lib/types/src/eth_sender.rs
+++ b/core/lib/types/src/eth_sender.rs
@@ -1,4 +1,5 @@
 use serde::{Deserialize, Serialize};
+use zksync_basic_types::SLChainId;
 
 use crate::{aggregated_operations::AggregatedActionType, Address, Nonce, H256};
 
@@ -52,6 +53,7 @@ pub struct EthTx {
     pub from_addr: Option<Address>,
     pub blob_sidecar: Option<EthTxBlobSidecar>,
     pub is_gateway: bool,
+    pub chain_id: Option<SLChainId>,
 }
 
 impl std::fmt::Debug for EthTx {
@@ -64,6 +66,7 @@ impl std::fmt::Debug for EthTx {
             .field("tx_type", &self.tx_type)
             .field("created_at_timestamp", &self.created_at_timestamp)
             .field("predicted_gas_cost", &self.predicted_gas_cost)
+            .field("chain_id", &self.chain_id)
             .finish()
     }
 }
diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs
index 856b79eb5c93..90d6e52cb8fb 100644
--- a/core/node/eth_sender/src/eth_tx_aggregator.rs
+++ b/core/node/eth_sender/src/eth_tx_aggregator.rs
@@ -20,8 +20,9 @@ use zksync_types::{
     l2_to_l1_log::UserL2ToL1Log,
     protocol_version::{L1VerifierConfig, PACKED_SEMVER_MINOR_MASK},
     pubdata_da::PubdataDA,
+    settlement::SettlementMode,
     web3::{contract::Error as Web3ContractError, BlockNumber},
-    Address, L2ChainId, ProtocolVersionId, H256, U256,
+    Address, L2ChainId, ProtocolVersionId, SLChainId, H256, U256,
 };
 
 use super::aggregated_operations::AggregatedOperation;
@@ -62,6 +63,8 @@ pub struct EthTxAggregator {
     /// address.
     custom_commit_sender_addr: Option<Address>,
     pool: ConnectionPool<Core>,
+    settlement_mode: SettlementMode,
+    sl_chain_id: SLChainId,
 }
 
 struct TxData {
@@ -81,6 +84,7 @@ impl EthTxAggregator {
         state_transition_chain_contract: Address,
         rollup_chain_id: L2ChainId,
         custom_commit_sender_addr: Option<Address>,
+        settlement_mode: SettlementMode,
     ) -> Self {
         let eth_client = eth_client.for_component("eth_tx_aggregator");
         let functions = ZkSyncFunctions::default();
@@ -97,6 +101,9 @@ impl EthTxAggregator {
             ),
             None => None,
         };
+
+        let sl_chain_id = (*eth_client).as_ref().fetch_chain_id().await.unwrap();
+
         Self {
             config,
             aggregator,
@@ -110,6 +117,8 @@ impl EthTxAggregator {
             rollup_chain_id,
             custom_commit_sender_addr,
             pool,
+            settlement_mode,
+            sl_chain_id,
         }
     }
 
@@ -578,6 +587,12 @@ impl EthTxAggregator {
             .await
             .unwrap();
 
+        transaction
+            .eth_sender_dal()
+            .set_chain_id(eth_tx.id, self.sl_chain_id.0)
+            .await
+            .unwrap();
+
         transaction
             .blocks_dal()
             .set_eth_tx_id(l1_batch_number_range, eth_tx.id, op_type)
@@ -592,9 +607,10 @@ impl EthTxAggregator {
         storage: &mut Connection<'_, Core>,
         from_addr: Option<Address>,
     ) -> Result<u64, EthSenderError> {
+        let is_gateway = self.settlement_mode == SettlementMode::Gateway;
         let db_nonce = storage
             .eth_sender_dal()
-            .get_next_nonce(from_addr)
+            .get_next_nonce(from_addr, is_gateway)
             .await
             .unwrap()
             .unwrap_or(0);
diff --git a/core/node/eth_sender/src/tester.rs b/core/node/eth_sender/src/tester.rs
index 508a38e61732..c6d993a9c97f 100644
--- a/core/node/eth_sender/src/tester.rs
+++ b/core/node/eth_sender/src/tester.rs
@@ -12,8 +12,8 @@ use zksync_node_test_utils::{create_l1_batch, l1_batch_metadata_to_commitment_ar
 use zksync_object_store::MockObjectStore;
 use zksync_types::{
     aggregated_operations::AggregatedActionType, block::L1BatchHeader,
-    commitment::L1BatchCommitmentMode, eth_sender::EthTx, pubdata_da::PubdataDA, Address,
-    L1BatchNumber, ProtocolVersion, H256,
+    commitment::L1BatchCommitmentMode, eth_sender::EthTx, pubdata_da::PubdataDA,
+    settlement::SettlementMode, Address, L1BatchNumber, ProtocolVersion, H256,
 };
 
 use crate::{
@@ -264,6 +264,7 @@ impl EthSenderTester {
             Address::random(),
             Default::default(),
             custom_commit_sender_addr,
+            SettlementMode::SettlesToL1,
         )
         .await;
 
diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
index 96fffcaf6a84..d6d6414e4383 100644
--- a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
+++ b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
@@ -3,12 +3,15 @@ use zksync_circuit_breaker::l1_txs::FailedL1TransactionChecker;
 use zksync_config::configs::{eth_sender::EthConfig, ContractsConfig};
 use zksync_eth_client::BoundEthInterface;
 use zksync_eth_sender::{Aggregator, EthTxAggregator};
-use zksync_types::{commitment::L1BatchCommitmentMode, L2ChainId};
+use zksync_types::{commitment::L1BatchCommitmentMode, settlement::SettlementMode, L2ChainId};
 
 use crate::{
     implementations::resources::{
         circuit_breakers::CircuitBreakersResource,
-        eth_interface::{BoundEthInterfaceForBlobsResource, BoundEthInterfaceResource},
+        eth_interface::{
+            BoundEthInterfaceForBlobsResource, BoundEthInterfaceForL2Resource,
+            BoundEthInterfaceResource,
+        },
         object_store::ObjectStoreResource,
         pools::{MasterPool, PoolResource, ReplicaPool},
     },
@@ -49,8 +52,9 @@ pub struct EthTxAggregatorLayer {
 pub struct Input {
     pub master_pool: PoolResource<MasterPool>,
     pub replica_pool: PoolResource<ReplicaPool>,
-    pub eth_client: BoundEthInterfaceResource,
+    pub eth_client: Option<BoundEthInterfaceResource>,
     pub eth_client_blobs: Option<BoundEthInterfaceForBlobsResource>,
+    pub eth_client_l2: Option<BoundEthInterfaceForL2Resource>,
     pub object_store: ObjectStoreResource,
     #[context(default)]
     pub circuit_breakers: CircuitBreakersResource,
@@ -93,7 +97,13 @@ impl WiringLayer for EthTxAggregatorLayer {
         let master_pool = input.master_pool.get().await.unwrap();
         let replica_pool = input.replica_pool.get().await.unwrap();
 
-        let eth_client = input.eth_client.0;
+        let (eth_client, settlement_mode) = match (input.eth_client_l2, input.eth_client) {
+            (Some(l1_client), None) => (l1_client.0, SettlementMode::SettlesToL1),
+            (None, Some(l2_client)) => (l2_client.0, SettlementMode::Gateway),
+            (_, _) => Err(WiringError::Configuration(
+                "Aggregator requires either l1 or l2 client to operatate".to_string(),
+            ))?,
+        };
         let eth_client_blobs = input.eth_client_blobs.map(|c| c.0);
         let object_store = input.object_store.0;
 
@@ -120,6 +130,7 @@ impl WiringLayer for EthTxAggregatorLayer {
             self.contracts_config.diamond_proxy_addr,
             self.zksync_network_id,
             eth_client_blobs_addr,
+            settlement_mode,
         )
         .await;
 

From f1da9a766c1aea19ffdf7307beb17cd8259546a0 Mon Sep 17 00:00:00 2001
From: tomg10 <lemures64@gmail.com>
Date: Mon, 19 Aug 2024 18:08:02 +0200
Subject: [PATCH 2/6] fix

Signed-off-by: tomg10 <lemures64@gmail.com>
---
 .../src/implementations/layers/eth_sender/aggregator.rs         | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
index d6d6414e4383..71a99fce777f 100644
--- a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
+++ b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
@@ -97,7 +97,7 @@ impl WiringLayer for EthTxAggregatorLayer {
         let master_pool = input.master_pool.get().await.unwrap();
         let replica_pool = input.replica_pool.get().await.unwrap();
 
-        let (eth_client, settlement_mode) = match (input.eth_client_l2, input.eth_client) {
+        let (eth_client, settlement_mode) = match (input.eth_client, input.eth_client_l2) {
             (Some(l1_client), None) => (l1_client.0, SettlementMode::SettlesToL1),
             (None, Some(l2_client)) => (l2_client.0, SettlementMode::Gateway),
             (_, _) => Err(WiringError::Configuration(

From c8603867134a6a2f2ef54f47ec207e0a2217e2a1 Mon Sep 17 00:00:00 2001
From: tomg10 <lemures64@gmail.com>
Date: Tue, 20 Aug 2024 16:09:38 +0200
Subject: [PATCH 3/6] PR feedback

Signed-off-by: tomg10 <lemures64@gmail.com>
---
 core/node/eth_sender/src/eth_tx_aggregator.rs                   | 2 +-
 .../src/implementations/layers/eth_sender/aggregator.rs         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/core/node/eth_sender/src/eth_tx_aggregator.rs b/core/node/eth_sender/src/eth_tx_aggregator.rs
index 90d6e52cb8fb..7d6a6b234742 100644
--- a/core/node/eth_sender/src/eth_tx_aggregator.rs
+++ b/core/node/eth_sender/src/eth_tx_aggregator.rs
@@ -607,7 +607,7 @@ impl EthTxAggregator {
         storage: &mut Connection<'_, Core>,
         from_addr: Option<Address>,
     ) -> Result<u64, EthSenderError> {
-        let is_gateway = self.settlement_mode == SettlementMode::Gateway;
+        let is_gateway = self.settlement_mode.is_gateway();
         let db_nonce = storage
             .eth_sender_dal()
             .get_next_nonce(from_addr, is_gateway)
diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
index 71a99fce777f..ba8b575142a7 100644
--- a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
+++ b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
@@ -101,7 +101,7 @@ impl WiringLayer for EthTxAggregatorLayer {
             (Some(l1_client), None) => (l1_client.0, SettlementMode::SettlesToL1),
             (None, Some(l2_client)) => (l2_client.0, SettlementMode::Gateway),
             (_, _) => Err(WiringError::Configuration(
-                "Aggregator requires either l1 or l2 client to operatate".to_string(),
+                "Aggregator requires either l1 or l2 client to operate".to_string(),
             ))?,
         };
         let eth_client_blobs = input.eth_client_blobs.map(|c| c.0);

From 14376ca76c360684796181a7418d293625afe0ca Mon Sep 17 00:00:00 2001
From: tomg10 <lemures64@gmail.com>
Date: Tue, 20 Aug 2024 16:23:08 +0200
Subject: [PATCH 4/6] PR feedback

Signed-off-by: tomg10 <lemures64@gmail.com>
---
 core/bin/zksync_server/src/node_builder.rs        |  5 +++++
 .../layers/eth_sender/aggregator.rs               | 15 ++++++++-------
 2 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/core/bin/zksync_server/src/node_builder.rs b/core/bin/zksync_server/src/node_builder.rs
index 7c4503876e9d..e713db65c77f 100644
--- a/core/bin/zksync_server/src/node_builder.rs
+++ b/core/bin/zksync_server/src/node_builder.rs
@@ -434,6 +434,11 @@ impl MainNodeBuilder {
             self.contracts_config.clone(),
             self.genesis_config.l2_chain_id,
             self.genesis_config.l1_batch_commit_data_generator_mode,
+            self.configs
+                .eth
+                .as_ref()
+                .and_then(|x| Some(x.gas_adjuster?.settlement_mode))
+                .unwrap_or(SettlementMode::SettlesToL1),
         ));
 
         Ok(self)
diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
index ba8b575142a7..9e16e990340c 100644
--- a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
+++ b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
@@ -45,6 +45,7 @@ pub struct EthTxAggregatorLayer {
     contracts_config: ContractsConfig,
     zksync_network_id: L2ChainId,
     l1_batch_commit_data_generator_mode: L1BatchCommitmentMode,
+    settlement_mode: SettlementMode,
 }
 
 #[derive(Debug, FromContext)]
@@ -73,12 +74,14 @@ impl EthTxAggregatorLayer {
         contracts_config: ContractsConfig,
         zksync_network_id: L2ChainId,
         l1_batch_commit_data_generator_mode: L1BatchCommitmentMode,
+        settlement_mode: SettlementMode,
     ) -> Self {
         Self {
             eth_sender_config,
             contracts_config,
             zksync_network_id,
             l1_batch_commit_data_generator_mode,
+            settlement_mode,
         }
     }
 }
@@ -97,12 +100,10 @@ impl WiringLayer for EthTxAggregatorLayer {
         let master_pool = input.master_pool.get().await.unwrap();
         let replica_pool = input.replica_pool.get().await.unwrap();
 
-        let (eth_client, settlement_mode) = match (input.eth_client, input.eth_client_l2) {
-            (Some(l1_client), None) => (l1_client.0, SettlementMode::SettlesToL1),
-            (None, Some(l2_client)) => (l2_client.0, SettlementMode::Gateway),
-            (_, _) => Err(WiringError::Configuration(
-                "Aggregator requires either l1 or l2 client to operate".to_string(),
-            ))?,
+        let eth_client = if self.settlement_mode.is_gateway() {
+            input.eth_client.context("l1_client")?.0
+        } else {
+            input.eth_client_l2.context("l1_client")?.0
         };
         let eth_client_blobs = input.eth_client_blobs.map(|c| c.0);
         let object_store = input.object_store.0;
@@ -130,7 +131,7 @@ impl WiringLayer for EthTxAggregatorLayer {
             self.contracts_config.diamond_proxy_addr,
             self.zksync_network_id,
             eth_client_blobs_addr,
-            settlement_mode,
+            self.settlement_mode,
         )
         .await;
 

From 6236d6b45fcd81062ed51eeaa25e21dd59a78a63 Mon Sep 17 00:00:00 2001
From: tomg10 <lemures64@gmail.com>
Date: Tue, 20 Aug 2024 16:26:33 +0200
Subject: [PATCH 5/6] PR feedback

Signed-off-by: tomg10 <lemures64@gmail.com>
---
 .../src/implementations/layers/eth_sender/aggregator.rs       | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
index 9e16e990340c..4d7f6ab449b6 100644
--- a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
+++ b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
@@ -101,9 +101,9 @@ impl WiringLayer for EthTxAggregatorLayer {
         let replica_pool = input.replica_pool.get().await.unwrap();
 
         let eth_client = if self.settlement_mode.is_gateway() {
-            input.eth_client.context("l1_client")?.0
+            input.eth_client.context("l1_client must be provided")?.0
         } else {
-            input.eth_client_l2.context("l1_client")?.0
+            input.eth_client_l2.context("l2_client must be provided")?.0
         };
         let eth_client_blobs = input.eth_client_blobs.map(|c| c.0);
         let object_store = input.object_store.0;

From fd2077bb907ac881d0fc2a61a4f779025397cf2d Mon Sep 17 00:00:00 2001
From: tomg10 <lemures64@gmail.com>
Date: Tue, 20 Aug 2024 16:42:12 +0200
Subject: [PATCH 6/6] fix

Signed-off-by: tomg10 <lemures64@gmail.com>
---
 .../src/implementations/layers/eth_sender/aggregator.rs       | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
index 4d7f6ab449b6..cfe701326bd6 100644
--- a/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
+++ b/core/node/node_framework/src/implementations/layers/eth_sender/aggregator.rs
@@ -101,9 +101,9 @@ impl WiringLayer for EthTxAggregatorLayer {
         let replica_pool = input.replica_pool.get().await.unwrap();
 
         let eth_client = if self.settlement_mode.is_gateway() {
-            input.eth_client.context("l1_client must be provided")?.0
-        } else {
             input.eth_client_l2.context("l2_client must be provided")?.0
+        } else {
+            input.eth_client.context("l1_client must be provided")?.0
         };
         let eth_client_blobs = input.eth_client_blobs.map(|c| c.0);
         let object_store = input.object_store.0;