From 87fc80f3403ff3398d5273c9a8aea9a66b618922 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 26 Jul 2024 14:10:12 +0200 Subject: [PATCH 01/85] Use forced price api client by default --- etc/env/base/external_price_api.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/env/base/external_price_api.toml b/etc/env/base/external_price_api.toml index bb22e86c432..6df93f7a550 100644 --- a/etc/env/base/external_price_api.toml +++ b/etc/env/base/external_price_api.toml @@ -6,5 +6,5 @@ source = "forced" [external_price_api_client.forced] -numerator = 3 -denominator = 2 +numerator = 314 +denominator = 100 From 0d8b4557dbb05229cc948100a6fd571e142ef954 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 29 Jul 2024 15:01:15 +0200 Subject: [PATCH 02/85] fix: smoothed ForcedPriceClient --- .../src/forced_price_client.rs | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index fd166cdfd2d..bee5d53fdf1 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -1,16 +1,24 @@ -use std::num::NonZeroU64; +use std::{ + cmp::{max, min}, + num::NonZeroU64, +}; use async_trait::async_trait; use rand::Rng; +use tokio::sync::RwLock; use zksync_config::configs::ExternalPriceApiClientConfig; use zksync_types::{base_token_ratio::BaseTokenAPIRatio, Address}; use crate::PriceAPIClient; -// Struct for a a forced price "client" (conversion ratio is always a configured "forced" ratio). -#[derive(Debug, Clone)] +const VARIATION_RANGE: f64 = 0.2; //20% +const NEXT_VALUE_VARIATION_RANGE: f64 = 0.03; //3% + +// Struct for a forced price "client" (conversion ratio is always a configured "forced" ratio). +#[derive(Debug)] pub struct ForcedPriceClient { ratio: BaseTokenAPIRatio, + previousNumerator: RwLock, fluctuation: Option, } @@ -36,6 +44,7 @@ impl ForcedPriceClient { denominator: NonZeroU64::new(denominator).unwrap(), ratio_timestamp: chrono::Utc::now(), }, + previousNumerator: RwLock::new(NonZeroU64::new(numerator).unwrap()), fluctuation, } } @@ -43,28 +52,33 @@ impl ForcedPriceClient { #[async_trait] impl PriceAPIClient for ForcedPriceClient { - // Returns a ratio which is 10% higher or lower than the configured forced ratio. + /// Returns a ratio which is 10% higher or lower than the configured forced ratio, + /// but not different more than 3% than the last value async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { - if let Some(x) = self.fluctuation { - if x != 0 { - let mut rng = rand::thread_rng(); + let mut previousNumerator = self.previousNumerator.write().await; + let mut rng = rand::thread_rng(); + let numerator_range = ( + max( + (self.ratio.numerator.get() as f64 * (1.0 - VARIATION_RANGE)).round() as u64, + (previousNumerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() + as u64, + ), + min( + (self.ratio.numerator.get() as f64 * (1.0 + VARIATION_RANGE)).round() as u64, + (previousNumerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() + as u64, + ), + ); - let mut adjust_range = |value: NonZeroU64| { - let value_f64 = value.get() as f64; - let min = (value_f64 * (1.0 - x as f64 / 100.0)).round() as u64; - let max = (value_f64 * (1.0 + x as f64 / 100.0)).round() as u64; - rng.gen_range(min..=max) - }; - let new_numerator = adjust_range(self.ratio.numerator); - let new_denominator = adjust_range(self.ratio.denominator); + let new_numerator = NonZeroU64::new(rng.gen_range(numerator_range.0..=numerator_range.1)) + .unwrap_or(self.ratio.numerator); + let adjusted_ratio = BaseTokenAPIRatio { + numerator: new_numerator, + denominator: self.ratio.denominator, + ratio_timestamp: chrono::Utc::now(), + }; + *previousNumerator = new_numerator; - return Ok(BaseTokenAPIRatio { - numerator: NonZeroU64::new(new_numerator).unwrap_or(self.ratio.numerator), - denominator: NonZeroU64::new(new_denominator).unwrap_or(self.ratio.denominator), - ratio_timestamp: chrono::Utc::now(), - }); - } - } - Ok(self.ratio) + Ok(adjusted_ratio) } } From 0ca2b5e4cdcb26b00e1f7b59ac10257d5eb50559 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 29 Jul 2024 15:08:41 +0200 Subject: [PATCH 03/85] feat: Integration test gas price incl calculation --- core/tests/ts-integration/tests/fees.test.ts | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 8d5b7a23a94..e8e70ce8f82 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -143,6 +143,32 @@ testFees('Test fees', () => { console.log(`Full report: \n\n${reports.join('\n\n')}`); }); + test.only('Test gas price expected value', async () => { + const receiver = ethers.Wallet.createRandom().address; + const l1GasPrice = 100_000_000_000n; /// set to 100 gwei + await setInternalL1GasPrice(alice._providerL2(), l1GasPrice.toString(), l1GasPrice.toString()); + + const receipt = await ( + await alice.sendTransaction({ + to: receiver, + value: BigInt(1) + }) + ).wait(); + + const expectedETHGasPrice = 100_000_000; + const expectedCustomGasPrice = expectedETHGasPrice * 3.14; + + const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); + const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; + if (isETHBasedChain) { + expect(receipt.gasPrice).toBe(BigInt(expectedETHGasPrice)); + } else { + // We need some tolerance here, becouse base token "forced" price provider has 10% randomness in its price + expect(receipt.gasPrice).toBeGreaterThan(expectedCustomGasPrice * 0.85); + expect(receipt.gasPrice).toBeLessThan(expectedCustomGasPrice * 1.15); + } + }); + test('Test gas consumption under large L1 gas price', async () => { if (testMaster.environment().l1BatchCommitDataGeneratorMode === DataAvailabityMode.Validium) { // We skip this test for Validium mode, since L1 gas price has little impact on the gasLimit in this mode. From f15bade54d7ee65bd6e1827ec81f09e7df7e66c1 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 30 Jul 2024 13:09:19 +0200 Subject: [PATCH 04/85] fix: Fetch base ratio immediately on start --- core/lib/external_price_api/src/forced_price_client.rs | 6 +++--- .../src/base_token_ratio_persister.rs | 10 +++++----- .../src/base_token_ratio_provider.rs | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index bee5d53fdf1..4a40712d47d 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -18,7 +18,7 @@ const NEXT_VALUE_VARIATION_RANGE: f64 = 0.03; //3% #[derive(Debug)] pub struct ForcedPriceClient { ratio: BaseTokenAPIRatio, - previousNumerator: RwLock, + previous_numerator: RwLock, fluctuation: Option, } @@ -44,7 +44,7 @@ impl ForcedPriceClient { denominator: NonZeroU64::new(denominator).unwrap(), ratio_timestamp: chrono::Utc::now(), }, - previousNumerator: RwLock::new(NonZeroU64::new(numerator).unwrap()), + previous_numerator: RwLock::new(NonZeroU64::new(numerator).unwrap()), fluctuation, } } @@ -55,7 +55,7 @@ impl PriceAPIClient for ForcedPriceClient { /// Returns a ratio which is 10% higher or lower than the configured forced ratio, /// but not different more than 3% than the last value async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { - let mut previousNumerator = self.previousNumerator.write().await; + let mut previousNumerator = self.previous_numerator.write().await; let mut rng = rand::thread_rng(); let numerator_range = ( max( diff --git a/core/node/base_token_adjuster/src/base_token_ratio_persister.rs b/core/node/base_token_adjuster/src/base_token_ratio_persister.rs index 12cd6233efb..96bd3b90b3d 100644 --- a/core/node/base_token_adjuster/src/base_token_ratio_persister.rs +++ b/core/node/base_token_adjuster/src/base_token_ratio_persister.rs @@ -59,11 +59,6 @@ impl BaseTokenRatioPersister { let mut timer = tokio::time::interval(self.config.price_polling_interval()); while !*stop_receiver.borrow_and_update() { - tokio::select! { - _ = timer.tick() => { /* continue iterations */ } - _ = stop_receiver.changed() => break, - } - if let Err(err) = self.loop_iteration().await { tracing::warn!( "Error in the base_token_ratio_persister loop interaction {}", @@ -74,6 +69,11 @@ impl BaseTokenRatioPersister { .context("Failed to execute a base_token_ratio_persister loop iteration"); } } + + tokio::select! { + _ = timer.tick() => { /* continue iterations */ } + _ = stop_receiver.changed() => break, + } } tracing::info!("Stop signal received, base_token_ratio_persister is shutting down"); diff --git a/core/node/base_token_adjuster/src/base_token_ratio_provider.rs b/core/node/base_token_adjuster/src/base_token_ratio_provider.rs index e16ea16ff0f..f8adf2ee214 100644 --- a/core/node/base_token_adjuster/src/base_token_ratio_provider.rs +++ b/core/node/base_token_adjuster/src/base_token_ratio_provider.rs @@ -48,13 +48,13 @@ impl DBBaseTokenRatioProvider { let mut timer = tokio::time::interval(self.config.price_cache_update_interval()); while !*stop_receiver.borrow_and_update() { + // TODO(PE-129): Implement latest ratio usability logic. + self.update_latest_price().await?; + tokio::select! { _ = timer.tick() => { /* continue iterations */ } _ = stop_receiver.changed() => break, } - - // TODO(PE-129): Implement latest ratio usability logic. - self.update_latest_price().await?; } tracing::info!("Stop signal received, base_token_ratio_provider is shutting down"); From ee7800b711968f287c725e68cff56c560bc63530 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 30 Jul 2024 15:46:47 +0200 Subject: [PATCH 05/85] fix: enable all fees tests --- core/tests/ts-integration/tests/fees.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index e8e70ce8f82..ff76304d5a6 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -143,7 +143,7 @@ testFees('Test fees', () => { console.log(`Full report: \n\n${reports.join('\n\n')}`); }); - test.only('Test gas price expected value', async () => { + test('Test gas price expected value', async () => { const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 100_000_000_000n; /// set to 100 gwei await setInternalL1GasPrice(alice._providerL2(), l1GasPrice.toString(), l1GasPrice.toString()); From 6112552beec793aba448fb3d70e2de5cbf89c5ef Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 31 Jul 2024 13:47:59 +0200 Subject: [PATCH 06/85] fix: increase alice wallet balance in fees.test.ts --- core/tests/ts-integration/tests/fees.test.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index ff76304d5a6..f26050f688f 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -17,6 +17,7 @@ import * as zksync from 'zksync-ethers'; import * as ethers from 'ethers'; import { DataAvailabityMode, Token } from '../src/types'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; +import { sendTransfers } from '../src/context-owner'; const UINT32_MAX = 2n ** 32n - 1n; const MAX_GAS_PER_PUBDATA = 50_000n; @@ -54,12 +55,24 @@ testFees('Test fees', () => { let tokenDetails: Token; let aliceErc20: zksync.Contract; - beforeAll(() => { + beforeAll(async () => { testMaster = TestMaster.getInstance(__filename); alice = testMaster.mainAccount(); tokenDetails = testMaster.environment().erc20Token; aliceErc20 = new ethers.Contract(tokenDetails.l1Address, zksync.utils.IERC20, alice.ethWallet()); + + const mainWallet = new zksync.Wallet( + testMaster.environment().mainWalletPK, + alice._providerL2(), + alice._providerL1() + ); + await sendTransfers( + zksync.utils.ETH_ADDRESS, + mainWallet, + { alice: alice.privateKey }, + ethers.parseEther('100') + ); }); test('Test fees', async () => { From e3e135686a39968554c547e946e38c249e816031 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 31 Jul 2024 13:52:01 +0200 Subject: [PATCH 07/85] fix: style --- core/lib/external_price_api/src/forced_price_client.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index 4a40712d47d..43a83c39720 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -55,17 +55,17 @@ impl PriceAPIClient for ForcedPriceClient { /// Returns a ratio which is 10% higher or lower than the configured forced ratio, /// but not different more than 3% than the last value async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { - let mut previousNumerator = self.previous_numerator.write().await; + let mut previous_numerator = self.previous_numerator.write().await; let mut rng = rand::thread_rng(); let numerator_range = ( max( (self.ratio.numerator.get() as f64 * (1.0 - VARIATION_RANGE)).round() as u64, - (previousNumerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() + (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() as u64, ), min( (self.ratio.numerator.get() as f64 * (1.0 + VARIATION_RANGE)).round() as u64, - (previousNumerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() + (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() as u64, ), ); @@ -77,7 +77,7 @@ impl PriceAPIClient for ForcedPriceClient { denominator: self.ratio.denominator, ratio_timestamp: chrono::Utc::now(), }; - *previousNumerator = new_numerator; + *previous_numerator = new_numerator; Ok(adjusted_ratio) } From fd5fa8b56e93e433ed180cec5055ec6efda39f42 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 31 Jul 2024 16:25:20 +0200 Subject: [PATCH 08/85] fix(tests): Kill with sigint --- core/tests/ts-integration/tests/fees.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index f26050f688f..1550d5e5adb 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -315,7 +315,7 @@ async function updateReport( } async function killServerAndWaitForShutdown(provider: zksync.Provider) { - await utils.exec('pkill zksync_server'); + await utils.exec('pkill --signal SIGINT zksync_server'); // Wait until it's really stopped. let iter = 0; while (iter < 30) { From 7592dfdabe79de501594ccd9b038e6c52d583400 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 31 Jul 2024 16:25:40 +0200 Subject: [PATCH 09/85] tmp: remove randomness in base token price --- .../src/forced_price_client.rs | 49 ++++++++++--------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index 43a83c39720..d6486e85a83 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -55,30 +55,35 @@ impl PriceAPIClient for ForcedPriceClient { /// Returns a ratio which is 10% higher or lower than the configured forced ratio, /// but not different more than 3% than the last value async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { - let mut previous_numerator = self.previous_numerator.write().await; - let mut rng = rand::thread_rng(); - let numerator_range = ( - max( - (self.ratio.numerator.get() as f64 * (1.0 - VARIATION_RANGE)).round() as u64, - (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() - as u64, - ), - min( - (self.ratio.numerator.get() as f64 * (1.0 + VARIATION_RANGE)).round() as u64, - (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() - as u64, - ), - ); - - let new_numerator = NonZeroU64::new(rng.gen_range(numerator_range.0..=numerator_range.1)) - .unwrap_or(self.ratio.numerator); - let adjusted_ratio = BaseTokenAPIRatio { - numerator: new_numerator, + Ok(BaseTokenAPIRatio { + numerator: self.ratio.numerator, denominator: self.ratio.denominator, ratio_timestamp: chrono::Utc::now(), - }; - *previous_numerator = new_numerator; + }) + // let mut previous_numerator = self.previous_numerator.write().await; + // let mut rng = rand::thread_rng(); + // let numerator_range = ( + // max( + // (self.ratio.numerator.get() as f64 * (1.0 - VARIATION_RANGE)).round() as u64, + // (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() + // as u64, + // ), + // min( + // (self.ratio.numerator.get() as f64 * (1.0 + VARIATION_RANGE)).round() as u64, + // (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() + // as u64, + // ), + // ); + // + // let new_numerator = NonZeroU64::new(rng.gen_range(numerator_range.0..=numerator_range.1)) + // .unwrap_or(self.ratio.numerator); + // let adjusted_ratio = BaseTokenAPIRatio { + // numerator: new_numerator, + // denominator: self.ratio.denominator, + // ratio_timestamp: chrono::Utc::now(), + // }; + // *previous_numerator = new_numerator; - Ok(adjusted_ratio) + // Ok(adjusted_ratio) } } From a656770f751019653cf1bca5b86f65f347dc69ee Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 31 Jul 2024 17:37:59 +0200 Subject: [PATCH 10/85] Try upgrade zksync-ethers to 6.11.0 --- core/tests/ts-integration/package.json | 2 +- yarn.lock | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/tests/ts-integration/package.json b/core/tests/ts-integration/package.json index 03bd84bb3f4..9fec6965926 100644 --- a/core/tests/ts-integration/package.json +++ b/core/tests/ts-integration/package.json @@ -30,7 +30,7 @@ "ts-jest": "^29.0.1", "ts-node": "^10.1.0", "typescript": "^4.3.5", - "zksync-ethers": "^6.9.0", + "zksync-ethers": "^6.11.0", "elliptic": "^6.5.5", "yaml": "^2.4.2" } diff --git a/yarn.lock b/yarn.lock index 173a06e631f..66677703430 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10879,6 +10879,11 @@ zksync-ethers@5.8.0-beta.5: dependencies: ethers "~5.7.0" +zksync-ethers@^6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-6.11.0.tgz#d36b77218407d4f4cdf4fa152768d41d2ceea4d5" + integrity sha512-l0s/8RkJ22e2/cXekrhgF005Xr/b7Lysd3uL9HiH5nvd8z4Sjragwh2kslrFAxmubbpF3wJsz0N8PpxcVIsGyg== + zksync-ethers@^6.9.0: version "6.9.0" resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-6.9.0.tgz#efaff1d59e2cff837eeda84c4ba59fdca4972a91" From ce0d00f600be438ca6f64e37201f3aa37db49ad1 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 31 Jul 2024 17:56:04 +0200 Subject: [PATCH 11/85] debug --- core/node/fee_model/src/lib.rs | 9 +++++++++ etc/env/base/rust.toml | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index 217ed71e38c..5bd819efdb3 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -226,6 +226,15 @@ fn compute_batch_fee_model_input_v2( l1_pubdata_price + pubdata_overhead_wei }; + tracing::debug!( + "Calculated gas prices L2: {} Pubdata: {}, L1 gas: {}, L1 pubdata: {}, L1 overhead: {}", + fair_l2_gas_price, + fair_pubdata_price, + l1_gas_price, + l1_pubdata_price, + l1_batch_overhead_wei + ); + PubdataIndependentBatchFeeModelInput { l1_gas_price, fair_l2_gas_price, diff --git a/etc/env/base/rust.toml b/etc/env/base/rust.toml index 1bb69374ab1..671a930f06c 100644 --- a/etc/env/base/rust.toml +++ b/etc/env/base/rust.toml @@ -10,7 +10,7 @@ zksync_block_reverter=info,\ zksync_commitment_generator=info,\ zksync_node_db_pruner=info,\ zksync_eth_sender=info,\ -zksync_node_fee_model=info,\ +zksync_node_fee_model=debug,\ zksync_node_genesis=info,\ zksync_house_keeper=info,\ zksync_proof_data_handler=info,\ @@ -25,7 +25,7 @@ zksync_metadata_calculator=info,\ zksync_node_sync=info,\ zksync_node_consensus=info,\ zksync_contract_verification_server=info,\ -zksync_node_api_server=info,\ +zksync_node_api_server=debug,\ zksync_tee_verifier_input_producer=info,\ zksync_consensus_bft=info,\ zksync_consensus_network=info,\ From 73cebecf38fdc63d2c1a2a98f3894b10d3fcf162 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 31 Jul 2024 18:14:15 +0200 Subject: [PATCH 12/85] Revert "Try upgrade zksync-ethers to 6.11.0" This reverts commit 7e3213fb30a49430c0c9702bba8c0dd2c00390c3. --- core/tests/ts-integration/package.json | 2 +- yarn.lock | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/core/tests/ts-integration/package.json b/core/tests/ts-integration/package.json index 9fec6965926..03bd84bb3f4 100644 --- a/core/tests/ts-integration/package.json +++ b/core/tests/ts-integration/package.json @@ -30,7 +30,7 @@ "ts-jest": "^29.0.1", "ts-node": "^10.1.0", "typescript": "^4.3.5", - "zksync-ethers": "^6.11.0", + "zksync-ethers": "^6.9.0", "elliptic": "^6.5.5", "yaml": "^2.4.2" } diff --git a/yarn.lock b/yarn.lock index 66677703430..173a06e631f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10879,11 +10879,6 @@ zksync-ethers@5.8.0-beta.5: dependencies: ethers "~5.7.0" -zksync-ethers@^6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-6.11.0.tgz#d36b77218407d4f4cdf4fa152768d41d2ceea4d5" - integrity sha512-l0s/8RkJ22e2/cXekrhgF005Xr/b7Lysd3uL9HiH5nvd8z4Sjragwh2kslrFAxmubbpF3wJsz0N8PpxcVIsGyg== - zksync-ethers@^6.9.0: version "6.9.0" resolved "https://registry.yarnpkg.com/zksync-ethers/-/zksync-ethers-6.9.0.tgz#efaff1d59e2cff837eeda84c4ba59fdca4972a91" From ecf18a46881d5cfc1596a785ef4595d3cd397971 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 12:39:10 +0200 Subject: [PATCH 13/85] fix: properly kill server after fees test --- core/tests/ts-integration/tests/fees.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 1550d5e5adb..3f7b5890e82 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -75,6 +75,10 @@ testFees('Test fees', () => { ); }); + afterAll(async () => { + await killServerAndWaitForShutdown(alice._providerL2()) + }) + test('Test fees', async () => { const receiver = ethers.Wallet.createRandom().address; From cb76faaa9859d6a8ec287fc173ff154c6cf5a215 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 12:39:27 +0200 Subject: [PATCH 14/85] Avoid gasEstimate in fees test --- core/tests/ts-integration/tests/fees.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 3f7b5890e82..ba24140afc6 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -168,7 +168,8 @@ testFees('Test fees', () => { const receipt = await ( await alice.sendTransaction({ to: receiver, - value: BigInt(1) + value: BigInt(1), + gasLimit: 1000000 }) ).wait(); From 04b023a53b5ea2b1c60755171d6c17977d2bccba Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 12:56:21 +0200 Subject: [PATCH 15/85] fix: style --- core/tests/ts-integration/tests/fees.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index ba24140afc6..3e10ae5b548 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -76,8 +76,8 @@ testFees('Test fees', () => { }); afterAll(async () => { - await killServerAndWaitForShutdown(alice._providerL2()) - }) + await killServerAndWaitForShutdown(alice._providerL2()); + }); test('Test fees', async () => { const receiver = ethers.Wallet.createRandom().address; From 79e691fb6cc4c78bec28ae56b951bb24af4bff25 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 13:33:05 +0200 Subject: [PATCH 16/85] debug: more logs --- core/node/fee_model/src/lib.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index 5bd819efdb3..b8b699b6605 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -227,12 +227,15 @@ fn compute_batch_fee_model_input_v2( }; tracing::debug!( - "Calculated gas prices L2: {} Pubdata: {}, L1 gas: {}, L1 pubdata: {}, L1 overhead: {}", + "Calculated gas prices L2: {} Pubdata: {}, L1 gas: {}, L1 pubdata: {}, L1 overhead: {}, max gas: {}, c_ohead: {}, p_ohead: {}", fair_l2_gas_price, fair_pubdata_price, l1_gas_price, l1_pubdata_price, - l1_batch_overhead_wei + l1_batch_overhead_wei, + max_gas_per_batch, + compute_overhead_part, + pubdata_overhead_part ); PubdataIndependentBatchFeeModelInput { From 8e554a222ab849015e1d0549e7055c56cdaed3c3 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 13:37:25 +0200 Subject: [PATCH 17/85] debug: log addresses --- core/tests/ts-integration/tests/fees.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 3e10ae5b548..406bad4435b 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -67,6 +67,8 @@ testFees('Test fees', () => { alice._providerL2(), alice._providerL1() ); + + console.log(`Alice address ${alice.address}. Main wallet address: ${mainWallet.address}`); await sendTransfers( zksync.utils.ETH_ADDRESS, mainWallet, From 50fcd6764595ef2fc00df1e41c42877b49ea9bc5 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 14:08:17 +0200 Subject: [PATCH 18/85] fix: increase test ETH per account due to large gas price test and remove transfer --- core/tests/ts-integration/src/context-owner.ts | 2 +- core/tests/ts-integration/tests/fees.test.ts | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/core/tests/ts-integration/src/context-owner.ts b/core/tests/ts-integration/src/context-owner.ts index 6cc2bed0a8d..161edd9248d 100644 --- a/core/tests/ts-integration/src/context-owner.ts +++ b/core/tests/ts-integration/src/context-owner.ts @@ -18,7 +18,7 @@ import { RetryProvider } from './retry-provider'; export const L1_DEFAULT_ETH_PER_ACCOUNT = ethers.parseEther('0.08'); // Stress tests for L1->L2 transactions on localhost require a lot of upfront payment, but these are skipped during tests on normal environments export const L1_EXTENDED_TESTS_ETH_PER_ACCOUNT = ethers.parseEther('0.5'); -export const L2_DEFAULT_ETH_PER_ACCOUNT = ethers.parseEther('0.5'); +export const L2_DEFAULT_ETH_PER_ACCOUNT = ethers.parseEther('5'); // Stress tests on local host may require a lot of additiomal funds, but these are skipped during tests on normal environments export const L2_EXTENDED_TESTS_ETH_PER_ACCOUNT = ethers.parseEther('50'); diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 406bad4435b..50a4818314a 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -67,14 +67,15 @@ testFees('Test fees', () => { alice._providerL2(), alice._providerL1() ); + console.log(`Main wallet balance: ${await mainWallet.getBalance()}`); console.log(`Alice address ${alice.address}. Main wallet address: ${mainWallet.address}`); - await sendTransfers( - zksync.utils.ETH_ADDRESS, - mainWallet, - { alice: alice.privateKey }, - ethers.parseEther('100') - ); + // await sendTransfers( + // zksync.utils.ETH_ADDRESS, + // mainWallet, + // { alice: alice.privateKey }, + // ethers.parseEther('100') + // ); }); afterAll(async () => { From baa526161553172c757ff22edce269b2d8d2abb2 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 14:37:31 +0200 Subject: [PATCH 19/85] Revert "fix: increase test ETH per account due to large gas price test and remove transfer" This reverts commit 838b8a250a1c2e31b6d396ccfd3155fbd1f4093f. --- core/tests/ts-integration/src/context-owner.ts | 2 +- core/tests/ts-integration/tests/fees.test.ts | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/core/tests/ts-integration/src/context-owner.ts b/core/tests/ts-integration/src/context-owner.ts index 161edd9248d..6cc2bed0a8d 100644 --- a/core/tests/ts-integration/src/context-owner.ts +++ b/core/tests/ts-integration/src/context-owner.ts @@ -18,7 +18,7 @@ import { RetryProvider } from './retry-provider'; export const L1_DEFAULT_ETH_PER_ACCOUNT = ethers.parseEther('0.08'); // Stress tests for L1->L2 transactions on localhost require a lot of upfront payment, but these are skipped during tests on normal environments export const L1_EXTENDED_TESTS_ETH_PER_ACCOUNT = ethers.parseEther('0.5'); -export const L2_DEFAULT_ETH_PER_ACCOUNT = ethers.parseEther('5'); +export const L2_DEFAULT_ETH_PER_ACCOUNT = ethers.parseEther('0.5'); // Stress tests on local host may require a lot of additiomal funds, but these are skipped during tests on normal environments export const L2_EXTENDED_TESTS_ETH_PER_ACCOUNT = ethers.parseEther('50'); diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 50a4818314a..406bad4435b 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -67,15 +67,14 @@ testFees('Test fees', () => { alice._providerL2(), alice._providerL1() ); - console.log(`Main wallet balance: ${await mainWallet.getBalance()}`); console.log(`Alice address ${alice.address}. Main wallet address: ${mainWallet.address}`); - // await sendTransfers( - // zksync.utils.ETH_ADDRESS, - // mainWallet, - // { alice: alice.privateKey }, - // ethers.parseEther('100') - // ); + await sendTransfers( + zksync.utils.ETH_ADDRESS, + mainWallet, + { alice: alice.privateKey }, + ethers.parseEther('100') + ); }); afterAll(async () => { From c5213b14d190640af085079c8cc643e815979a81 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 15:31:50 +0200 Subject: [PATCH 20/85] fix(test): Increase fees.test.ts alice account balance --- core/tests/ts-integration/tests/fees.test.ts | 37 +++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 406bad4435b..b137c8f49ae 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -18,6 +18,7 @@ import * as ethers from 'ethers'; import { DataAvailabityMode, Token } from '../src/types'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; import { sendTransfers } from '../src/context-owner'; +import { Reporter } from '../src/reporter'; const UINT32_MAX = 2n ** 32n - 1n; const MAX_GAS_PER_PUBDATA = 50_000n; @@ -68,12 +69,38 @@ testFees('Test fees', () => { alice._providerL1() ); + const bridgehub = await mainWallet.getBridgehubContract(); + const chainId = testMaster.environment().l2ChainId; + const baseTokenAddress = await bridgehub.baseToken(chainId); + console.log(`Alice address ${alice.address}. Main wallet address: ${mainWallet.address}`); - await sendTransfers( - zksync.utils.ETH_ADDRESS, - mainWallet, - { alice: alice.privateKey }, - ethers.parseEther('100') + console.log( + `Before deposit: Alice balance ${ethers.formatEther( + await alice.getBalance() + )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` + ); + const depositTx = await mainWallet.deposit({ + token: baseTokenAddress, + amount: ethers.parseEther('100'), + approveERC20: true, + approveBaseERC20: true + }); + await depositTx.wait(); + await Promise.all( + await sendTransfers( + zksync.utils.ETH_ADDRESS, + mainWallet, + { alice: alice.privateKey }, + ethers.parseEther('100'), + undefined, + undefined, + new Reporter() + ) + ); + console.log( + `After deposit: Alice balance ${ethers.formatEther( + await alice.getBalance() + )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` ); }); From 644c230b0b889281da707c9da0f069bb5dc89a6e Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 1 Aug 2024 17:31:04 +0200 Subject: [PATCH 21/85] fix(test): Lower l1 gas price in expected gas price test --- core/tests/ts-integration/tests/fees.test.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index b137c8f49ae..fe53c650a10 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -104,10 +104,6 @@ testFees('Test fees', () => { ); }); - afterAll(async () => { - await killServerAndWaitForShutdown(alice._providerL2()); - }); - test('Test fees', async () => { const receiver = ethers.Wallet.createRandom().address; @@ -191,7 +187,7 @@ testFees('Test fees', () => { test('Test gas price expected value', async () => { const receiver = ethers.Wallet.createRandom().address; - const l1GasPrice = 100_000_000_000n; /// set to 100 gwei + const l1GasPrice = 10_000_000_000n; /// set to 10 gwei await setInternalL1GasPrice(alice._providerL2(), l1GasPrice.toString(), l1GasPrice.toString()); const receipt = await ( @@ -202,7 +198,7 @@ testFees('Test fees', () => { }) ).wait(); - const expectedETHGasPrice = 100_000_000; + const expectedETHGasPrice = 100_000_000; /// 0.1 gwei (the minimum) const expectedCustomGasPrice = expectedETHGasPrice * 3.14; const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); From 0a9676be2ec02178d86ed5dfc1c56e020e1bc565 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 2 Aug 2024 11:50:28 +0200 Subject: [PATCH 22/85] fix(test): Lower l1 gas price in expected gas price test even more --- core/tests/ts-integration/tests/fees.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index fe53c650a10..4ffa26e8e4d 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -187,7 +187,7 @@ testFees('Test fees', () => { test('Test gas price expected value', async () => { const receiver = ethers.Wallet.createRandom().address; - const l1GasPrice = 10_000_000_000n; /// set to 10 gwei + const l1GasPrice = 2_000_000_000n; /// set to 2 gwei await setInternalL1GasPrice(alice._providerL2(), l1GasPrice.toString(), l1GasPrice.toString()); const receipt = await ( From 46d541435e10f7cdbc180070d7ac699c96872518 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 2 Aug 2024 11:52:01 +0200 Subject: [PATCH 23/85] Revert "Avoid gasEstimate in fees test" This reverts commit 90183b3706f9bede4a28454f2edb716b81cec342. --- core/tests/ts-integration/tests/fees.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 4ffa26e8e4d..3fbadeb6c4a 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -193,8 +193,7 @@ testFees('Test fees', () => { const receipt = await ( await alice.sendTransaction({ to: receiver, - value: BigInt(1), - gasLimit: 1000000 + value: BigInt(1) }) ).wait(); From c902dc269197c77b3c0964e89ce40009eab66727 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 2 Aug 2024 11:52:50 +0200 Subject: [PATCH 24/85] Revert "tmp: remove randomness in base token price" This reverts commit 6b330a476de043ecd9a1dd1497c1ecf76a759192. --- .../src/forced_price_client.rs | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index d6486e85a83..43a83c39720 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -55,35 +55,30 @@ impl PriceAPIClient for ForcedPriceClient { /// Returns a ratio which is 10% higher or lower than the configured forced ratio, /// but not different more than 3% than the last value async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { - Ok(BaseTokenAPIRatio { - numerator: self.ratio.numerator, + let mut previous_numerator = self.previous_numerator.write().await; + let mut rng = rand::thread_rng(); + let numerator_range = ( + max( + (self.ratio.numerator.get() as f64 * (1.0 - VARIATION_RANGE)).round() as u64, + (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() + as u64, + ), + min( + (self.ratio.numerator.get() as f64 * (1.0 + VARIATION_RANGE)).round() as u64, + (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() + as u64, + ), + ); + + let new_numerator = NonZeroU64::new(rng.gen_range(numerator_range.0..=numerator_range.1)) + .unwrap_or(self.ratio.numerator); + let adjusted_ratio = BaseTokenAPIRatio { + numerator: new_numerator, denominator: self.ratio.denominator, ratio_timestamp: chrono::Utc::now(), - }) - // let mut previous_numerator = self.previous_numerator.write().await; - // let mut rng = rand::thread_rng(); - // let numerator_range = ( - // max( - // (self.ratio.numerator.get() as f64 * (1.0 - VARIATION_RANGE)).round() as u64, - // (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() - // as u64, - // ), - // min( - // (self.ratio.numerator.get() as f64 * (1.0 + VARIATION_RANGE)).round() as u64, - // (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() - // as u64, - // ), - // ); - // - // let new_numerator = NonZeroU64::new(rng.gen_range(numerator_range.0..=numerator_range.1)) - // .unwrap_or(self.ratio.numerator); - // let adjusted_ratio = BaseTokenAPIRatio { - // numerator: new_numerator, - // denominator: self.ratio.denominator, - // ratio_timestamp: chrono::Utc::now(), - // }; - // *previous_numerator = new_numerator; + }; + *previous_numerator = new_numerator; - // Ok(adjusted_ratio) + Ok(adjusted_ratio) } } From 93126b54d28e83078beed4e7bf192b43b81ac09a Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 2 Aug 2024 12:25:03 +0200 Subject: [PATCH 25/85] fix: add validium compute overhead --- core/tests/ts-integration/tests/fees.test.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 3fbadeb6c4a..4be031c470b 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -197,7 +197,10 @@ testFees('Test fees', () => { }) ).wait(); - const expectedETHGasPrice = 100_000_000; /// 0.1 gwei (the minimum) + const expectedETHGasPrice = + testMaster.environment().l1BatchCommitDataGeneratorMode === DataAvailabityMode.Rollup + ? 100_000_000 // 0.1 gwei (the minimum) + : 110_000_000; // 0.11 gwei, in validium we need to add compute overhead const expectedCustomGasPrice = expectedETHGasPrice * 3.14; const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); From 358769d746882569366bc12ccc55e70ce50b60fd Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Thu, 15 Aug 2024 13:54:27 +0100 Subject: [PATCH 26/85] fix tests --- core/node/fee_model/src/lib.rs | 12 ------- core/tests/ts-integration/src/test-master.ts | 33 ++++++++++++++++++-- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index b8b699b6605..217ed71e38c 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -226,18 +226,6 @@ fn compute_batch_fee_model_input_v2( l1_pubdata_price + pubdata_overhead_wei }; - tracing::debug!( - "Calculated gas prices L2: {} Pubdata: {}, L1 gas: {}, L1 pubdata: {}, L1 overhead: {}, max gas: {}, c_ohead: {}, p_ohead: {}", - fair_l2_gas_price, - fair_pubdata_price, - l1_gas_price, - l1_pubdata_price, - l1_batch_overhead_wei, - max_gas_per_batch, - compute_overhead_part, - pubdata_overhead_part - ); - PubdataIndependentBatchFeeModelInput { l1_gas_price, fair_l2_gas_price, diff --git a/core/tests/ts-integration/src/test-master.ts b/core/tests/ts-integration/src/test-master.ts index 09fddd1589c..db4494a9651 100644 --- a/core/tests/ts-integration/src/test-master.ts +++ b/core/tests/ts-integration/src/test-master.ts @@ -5,6 +5,35 @@ import { claimEtherBack } from './context-owner'; import { RetryProvider } from './retry-provider'; import { Reporter } from './reporter'; import { bigIntReviver } from './helpers'; +import { TransactionLike, TransactionRequest } from 'zksync-ethers/build/types'; +import { getBigInt } from 'ethers'; + +export class BumpUpFeeWallet extends zksync.Wallet { + constructor(privateKey: string | ethers.SigningKey, providerL2?: zksync.Provider, providerL1?: ethers.Provider) { + super(privateKey, providerL2, providerL1); + } + + override async populateTransaction(tx: TransactionRequest): Promise { + const baseToken = await this._providerL2().getBaseTokenContractAddress(); + const isETHBasedChain = zksync.utils.isAddressEq(baseToken, zksync.utils.ETH_ADDRESS_IN_CONTRACTS); + // this is how much percent up we bumping up the fee to account for token price fluctuations + const adjustment = 30; + + return super.populateTransaction(tx).then((result) => { + if (isETHBasedChain) { + return result; + } else { + } + if (result.maxFeePerGas) { + result.maxFeePerGas = (BigInt(100 + adjustment) * getBigInt(result.maxFeePerGas)) / BigInt(100); + } + if (result.gasPrice) { + result.gasPrice = (BigInt(100 + adjustment) * getBigInt(result.gasPrice)) / BigInt(100); + } + return result; + }); + } +} /** * Test master is a singleton class (per suite) that is capable of providing wallets to the suite. @@ -71,7 +100,7 @@ export class TestMaster { this.l2Provider.pollingInterval = 5000; } - this.mainWallet = new zksync.Wallet(suiteWalletPK, this.l2Provider, this.l1Provider); + this.mainWallet = new BumpUpFeeWallet(suiteWalletPK, this.l2Provider, this.l1Provider); } /** @@ -112,7 +141,7 @@ export class TestMaster { */ newEmptyAccount(): zksync.Wallet { const randomPK = ethers.Wallet.createRandom().privateKey; - const newWallet = new zksync.Wallet(randomPK, this.l2Provider, this.l1Provider); + const newWallet = new BumpUpFeeWallet(randomPK, this.l2Provider, this.l1Provider); this.subAccounts.push(newWallet); return newWallet; } From 6c1f1af6f4e4fec9c277e5cf1213a0bf1a1ec1f0 Mon Sep 17 00:00:00 2001 From: Ivan Schasny Date: Fri, 16 Aug 2024 10:34:29 +0100 Subject: [PATCH 27/85] reduce variation range --- core/lib/external_price_api/src/forced_price_client.rs | 4 ++-- core/tests/ts-integration/src/test-master.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index 43a83c39720..1bab2f945c5 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -11,8 +11,8 @@ use zksync_types::{base_token_ratio::BaseTokenAPIRatio, Address}; use crate::PriceAPIClient; -const VARIATION_RANGE: f64 = 0.2; //20% -const NEXT_VALUE_VARIATION_RANGE: f64 = 0.03; //3% +const VARIATION_RANGE: f64 = 0.03; //20% +const NEXT_VALUE_VARIATION_RANGE: f64 = 0.01; //3% // Struct for a forced price "client" (conversion ratio is always a configured "forced" ratio). #[derive(Debug)] diff --git a/core/tests/ts-integration/src/test-master.ts b/core/tests/ts-integration/src/test-master.ts index db4494a9651..fa6a8e12f5a 100644 --- a/core/tests/ts-integration/src/test-master.ts +++ b/core/tests/ts-integration/src/test-master.ts @@ -100,7 +100,7 @@ export class TestMaster { this.l2Provider.pollingInterval = 5000; } - this.mainWallet = new BumpUpFeeWallet(suiteWalletPK, this.l2Provider, this.l1Provider); + this.mainWallet = new zksync.Wallet(suiteWalletPK, this.l2Provider, this.l1Provider); } /** @@ -141,7 +141,7 @@ export class TestMaster { */ newEmptyAccount(): zksync.Wallet { const randomPK = ethers.Wallet.createRandom().privateKey; - const newWallet = new BumpUpFeeWallet(randomPK, this.l2Provider, this.l1Provider); + const newWallet = new zksync.Wallet(randomPK, this.l2Provider, this.l1Provider); this.subAccounts.push(newWallet); return newWallet; } From 068a7aa7d4b56949acc621af5ab0d382b4a37ae9 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 26 Aug 2024 15:01:54 +0200 Subject: [PATCH 28/85] fix: actually use fluctuation --- .../src/forced_price_client.rs | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index 1bab2f945c5..b81900882b6 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -11,8 +11,7 @@ use zksync_types::{base_token_ratio::BaseTokenAPIRatio, Address}; use crate::PriceAPIClient; -const VARIATION_RANGE: f64 = 0.03; //20% -const NEXT_VALUE_VARIATION_RANGE: f64 = 0.01; //3% +const NEXT_VALUE_VARIATION_RANGE: f64 = 0.03; //3% // Struct for a forced price "client" (conversion ratio is always a configured "forced" ratio). #[derive(Debug)] @@ -55,30 +54,36 @@ impl PriceAPIClient for ForcedPriceClient { /// Returns a ratio which is 10% higher or lower than the configured forced ratio, /// but not different more than 3% than the last value async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { - let mut previous_numerator = self.previous_numerator.write().await; - let mut rng = rand::thread_rng(); - let numerator_range = ( - max( - (self.ratio.numerator.get() as f64 * (1.0 - VARIATION_RANGE)).round() as u64, - (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() - as u64, - ), - min( - (self.ratio.numerator.get() as f64 * (1.0 + VARIATION_RANGE)).round() as u64, - (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() - as u64, - ), - ); + if let Some(fluctation) = self.fluctuation { + let mut previous_numerator = self.previous_numerator.write().await; + let mut rng = rand::thread_rng(); + let numerator_range = ( + max( + (self.ratio.numerator.get() as f64 * (1.0 - (fluctation as f64 / 100.0))) + .round() as u64, + (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() + as u64, + ), + min( + (self.ratio.numerator.get() as f64 * (1.0 + (fluctation as f64 / 100.0))) + .round() as u64, + (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() + as u64, + ), + ); - let new_numerator = NonZeroU64::new(rng.gen_range(numerator_range.0..=numerator_range.1)) - .unwrap_or(self.ratio.numerator); - let adjusted_ratio = BaseTokenAPIRatio { - numerator: new_numerator, - denominator: self.ratio.denominator, - ratio_timestamp: chrono::Utc::now(), - }; - *previous_numerator = new_numerator; - - Ok(adjusted_ratio) + let new_numerator = + NonZeroU64::new(rng.gen_range(numerator_range.0..=numerator_range.1)) + .unwrap_or(self.ratio.numerator); + let adjusted_ratio = BaseTokenAPIRatio { + numerator: new_numerator, + denominator: self.ratio.denominator, + ratio_timestamp: chrono::Utc::now(), + }; + *previous_numerator = new_numerator; + Ok(adjusted_ratio) + } else { + Ok(self.ratio) + } } } From b443cfa7ab7040f5bfb5586d986065785db92311 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 27 Aug 2024 17:44:55 +0200 Subject: [PATCH 29/85] Revert "fix tests" This reverts commit 358769d746882569366bc12ccc55e70ce50b60fd. --- core/node/fee_model/src/lib.rs | 12 ++++++++ core/tests/ts-integration/src/test-master.ts | 29 -------------------- 2 files changed, 12 insertions(+), 29 deletions(-) diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index 217ed71e38c..b8b699b6605 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -226,6 +226,18 @@ fn compute_batch_fee_model_input_v2( l1_pubdata_price + pubdata_overhead_wei }; + tracing::debug!( + "Calculated gas prices L2: {} Pubdata: {}, L1 gas: {}, L1 pubdata: {}, L1 overhead: {}, max gas: {}, c_ohead: {}, p_ohead: {}", + fair_l2_gas_price, + fair_pubdata_price, + l1_gas_price, + l1_pubdata_price, + l1_batch_overhead_wei, + max_gas_per_batch, + compute_overhead_part, + pubdata_overhead_part + ); + PubdataIndependentBatchFeeModelInput { l1_gas_price, fair_l2_gas_price, diff --git a/core/tests/ts-integration/src/test-master.ts b/core/tests/ts-integration/src/test-master.ts index fa6a8e12f5a..09fddd1589c 100644 --- a/core/tests/ts-integration/src/test-master.ts +++ b/core/tests/ts-integration/src/test-master.ts @@ -5,35 +5,6 @@ import { claimEtherBack } from './context-owner'; import { RetryProvider } from './retry-provider'; import { Reporter } from './reporter'; import { bigIntReviver } from './helpers'; -import { TransactionLike, TransactionRequest } from 'zksync-ethers/build/types'; -import { getBigInt } from 'ethers'; - -export class BumpUpFeeWallet extends zksync.Wallet { - constructor(privateKey: string | ethers.SigningKey, providerL2?: zksync.Provider, providerL1?: ethers.Provider) { - super(privateKey, providerL2, providerL1); - } - - override async populateTransaction(tx: TransactionRequest): Promise { - const baseToken = await this._providerL2().getBaseTokenContractAddress(); - const isETHBasedChain = zksync.utils.isAddressEq(baseToken, zksync.utils.ETH_ADDRESS_IN_CONTRACTS); - // this is how much percent up we bumping up the fee to account for token price fluctuations - const adjustment = 30; - - return super.populateTransaction(tx).then((result) => { - if (isETHBasedChain) { - return result; - } else { - } - if (result.maxFeePerGas) { - result.maxFeePerGas = (BigInt(100 + adjustment) * getBigInt(result.maxFeePerGas)) / BigInt(100); - } - if (result.gasPrice) { - result.gasPrice = (BigInt(100 + adjustment) * getBigInt(result.gasPrice)) / BigInt(100); - } - return result; - }); - } -} /** * Test master is a singleton class (per suite) that is capable of providing wallets to the suite. From af9332c97cefb4762a945ef1ad6819fb2652ecd6 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 27 Aug 2024 20:49:39 +0200 Subject: [PATCH 30/85] Revert "reduce variation range" This reverts commit 6c1f1af6f4e4fec9c277e5cf1213a0bf1a1ec1f0. --- core/tests/ts-integration/src/test-master.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tests/ts-integration/src/test-master.ts b/core/tests/ts-integration/src/test-master.ts index 09fddd1589c..4b2a6fb7fc8 100644 --- a/core/tests/ts-integration/src/test-master.ts +++ b/core/tests/ts-integration/src/test-master.ts @@ -71,7 +71,7 @@ export class TestMaster { this.l2Provider.pollingInterval = 5000; } - this.mainWallet = new zksync.Wallet(suiteWalletPK, this.l2Provider, this.l1Provider); + this.mainWallet = new BumpUpFeeWallet(suiteWalletPK, this.l2Provider, this.l1Provider); } /** @@ -112,7 +112,7 @@ export class TestMaster { */ newEmptyAccount(): zksync.Wallet { const randomPK = ethers.Wallet.createRandom().privateKey; - const newWallet = new zksync.Wallet(randomPK, this.l2Provider, this.l1Provider); + const newWallet = new BumpUpFeeWallet(randomPK, this.l2Provider, this.l1Provider); this.subAccounts.push(newWallet); return newWallet; } From 452ea58252f56c8ec1546a257d300c8b3a3fdc1d Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 27 Aug 2024 21:07:45 +0200 Subject: [PATCH 31/85] Remove BumpUpFeeWallet leftovers --- core/tests/ts-integration/src/test-master.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tests/ts-integration/src/test-master.ts b/core/tests/ts-integration/src/test-master.ts index 4b2a6fb7fc8..09fddd1589c 100644 --- a/core/tests/ts-integration/src/test-master.ts +++ b/core/tests/ts-integration/src/test-master.ts @@ -71,7 +71,7 @@ export class TestMaster { this.l2Provider.pollingInterval = 5000; } - this.mainWallet = new BumpUpFeeWallet(suiteWalletPK, this.l2Provider, this.l1Provider); + this.mainWallet = new zksync.Wallet(suiteWalletPK, this.l2Provider, this.l1Provider); } /** @@ -112,7 +112,7 @@ export class TestMaster { */ newEmptyAccount(): zksync.Wallet { const randomPK = ethers.Wallet.createRandom().privateKey; - const newWallet = new BumpUpFeeWallet(randomPK, this.l2Provider, this.l1Provider); + const newWallet = new zksync.Wallet(randomPK, this.l2Provider, this.l1Provider); this.subAccounts.push(newWallet); return newWallet; } From 90b345abfa0f8d0e9ac146de0bfc936b6d8ca116 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 27 Aug 2024 23:10:48 +0200 Subject: [PATCH 32/85] feat: do not display Obtained receipt... debug logs by default --- core/tests/ts-integration/src/retry-provider.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/tests/ts-integration/src/retry-provider.ts b/core/tests/ts-integration/src/retry-provider.ts index 1763c0e4edf..7a04a8b2712 100644 --- a/core/tests/ts-integration/src/retry-provider.ts +++ b/core/tests/ts-integration/src/retry-provider.ts @@ -57,9 +57,10 @@ export class RetryProvider extends zksync.Provider { override _wrapTransactionReceipt(receipt: any): zksync.types.TransactionReceipt { const wrapped = super._wrapTransactionReceipt(receipt); - this.reporter.debug( - `Obtained receipt for transaction ${receipt.transactionHash}: blockNumber=${receipt.blockNumber}, status=${receipt.status}` - ); + if (process.env.ZKSYNC_DEBUG_TX_RECEIPT) + this.reporter.debug( + `Obtained receipt for transaction ${receipt.transactionHash}: blockNumber=${receipt.blockNumber}, status=${receipt.status}` + ); return wrapped; } } From f171a46eca15108d08ac169ee5ba0f7594731c97 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 27 Aug 2024 23:12:53 +0200 Subject: [PATCH 33/85] Remove gas price debug log --- core/node/fee_model/src/lib.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/core/node/fee_model/src/lib.rs b/core/node/fee_model/src/lib.rs index b8b699b6605..217ed71e38c 100644 --- a/core/node/fee_model/src/lib.rs +++ b/core/node/fee_model/src/lib.rs @@ -226,18 +226,6 @@ fn compute_batch_fee_model_input_v2( l1_pubdata_price + pubdata_overhead_wei }; - tracing::debug!( - "Calculated gas prices L2: {} Pubdata: {}, L1 gas: {}, L1 pubdata: {}, L1 overhead: {}, max gas: {}, c_ohead: {}, p_ohead: {}", - fair_l2_gas_price, - fair_pubdata_price, - l1_gas_price, - l1_pubdata_price, - l1_batch_overhead_wei, - max_gas_per_batch, - compute_overhead_part, - pubdata_overhead_part - ); - PubdataIndependentBatchFeeModelInput { l1_gas_price, fair_l2_gas_price, From e8115ada1626591016390a6d90e6ad0714921bd7 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 27 Aug 2024 23:43:36 +0200 Subject: [PATCH 34/85] fix: adjust base token test expected ratio --- core/tests/ts-integration/tests/base-token.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tests/ts-integration/tests/base-token.test.ts b/core/tests/ts-integration/tests/base-token.test.ts index adb32def5b0..4197451136a 100644 --- a/core/tests/ts-integration/tests/base-token.test.ts +++ b/core/tests/ts-integration/tests/base-token.test.ts @@ -37,8 +37,8 @@ describe('base ERC20 contract checks', () => { const denominator = Number(await zksyncContract.baseTokenGasPriceMultiplierDenominator()); // checking that the numerator and denominator don't have their default values - expect(numerator).toBe(3); - expect(denominator).toBe(2); + expect(numerator).toBe(314); + expect(denominator).toBe(100); }); test('Can perform a deposit', async () => { From 06abea9c5fe3a72677d5fb679f58f5886d72c499 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 28 Aug 2024 13:52:12 +0200 Subject: [PATCH 35/85] feat: reenable forced client price fluctuation --- core/tests/ts-integration/tests/base-token.test.ts | 5 +++-- etc/env/base/external_price_api.toml | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/tests/ts-integration/tests/base-token.test.ts b/core/tests/ts-integration/tests/base-token.test.ts index 4197451136a..4d12967d38b 100644 --- a/core/tests/ts-integration/tests/base-token.test.ts +++ b/core/tests/ts-integration/tests/base-token.test.ts @@ -36,8 +36,9 @@ describe('base ERC20 contract checks', () => { const numerator = Number(await zksyncContract.baseTokenGasPriceMultiplierNominator()); const denominator = Number(await zksyncContract.baseTokenGasPriceMultiplierDenominator()); - // checking that the numerator and denominator don't have their default values - expect(numerator).toBe(314); + // checking that the numerator and denominator have appropriate values (there is 10% randomness, so we have 15% tolerance) + expect(numerator).toBeGreaterThan(314 * 0.85); + expect(numerator).toBeLessThan(314 * 1.15); expect(denominator).toBe(100); }); diff --git a/etc/env/base/external_price_api.toml b/etc/env/base/external_price_api.toml index 6df93f7a550..a7239a8838e 100644 --- a/etc/env/base/external_price_api.toml +++ b/etc/env/base/external_price_api.toml @@ -8,3 +8,4 @@ source = "forced" [external_price_api_client.forced] numerator = 314 denominator = 100 +fluctuation = 10 \ No newline at end of file From 64bf3bc2f53a00c6cc036f4be7e55a52bdc250cc Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 28 Aug 2024 14:34:35 +0200 Subject: [PATCH 36/85] fix: lower forced ratio value by /10 due to not enough funds for some operations in custom base token tests --- core/tests/ts-integration/tests/base-token.test.ts | 2 +- core/tests/ts-integration/tests/fees.test.ts | 2 +- etc/env/base/external_price_api.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/tests/ts-integration/tests/base-token.test.ts b/core/tests/ts-integration/tests/base-token.test.ts index 4d12967d38b..14c60d43560 100644 --- a/core/tests/ts-integration/tests/base-token.test.ts +++ b/core/tests/ts-integration/tests/base-token.test.ts @@ -39,7 +39,7 @@ describe('base ERC20 contract checks', () => { // checking that the numerator and denominator have appropriate values (there is 10% randomness, so we have 15% tolerance) expect(numerator).toBeGreaterThan(314 * 0.85); expect(numerator).toBeLessThan(314 * 1.15); - expect(denominator).toBe(100); + expect(denominator).toBe(1000); }); test('Can perform a deposit', async () => { diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 4be031c470b..39bca17e371 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -201,7 +201,7 @@ testFees('Test fees', () => { testMaster.environment().l1BatchCommitDataGeneratorMode === DataAvailabityMode.Rollup ? 100_000_000 // 0.1 gwei (the minimum) : 110_000_000; // 0.11 gwei, in validium we need to add compute overhead - const expectedCustomGasPrice = expectedETHGasPrice * 3.14; + const expectedCustomGasPrice = expectedETHGasPrice * 0.314; const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; diff --git a/etc/env/base/external_price_api.toml b/etc/env/base/external_price_api.toml index a7239a8838e..cd6fbe4ce69 100644 --- a/etc/env/base/external_price_api.toml +++ b/etc/env/base/external_price_api.toml @@ -7,5 +7,5 @@ source = "forced" [external_price_api_client.forced] numerator = 314 -denominator = 100 +denominator = 1000 fluctuation = 10 \ No newline at end of file From 33ca127677f0eb0a74516768047fe0d46a8909ba Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 28 Aug 2024 20:35:37 +0200 Subject: [PATCH 37/85] feat: add reason of setTokenMultiplier failure --- .../src/base_token_ratio_persister.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/node/base_token_adjuster/src/base_token_ratio_persister.rs b/core/node/base_token_adjuster/src/base_token_ratio_persister.rs index 96bd3b90b3d..215042907dd 100644 --- a/core/node/base_token_adjuster/src/base_token_ratio_persister.rs +++ b/core/node/base_token_adjuster/src/base_token_ratio_persister.rs @@ -314,10 +314,16 @@ impl BaseTokenRatioPersister { if receipt.status == Some(1.into()) { return Ok(receipt.gas_used); } + let reason = (*l1_params.eth_client) + .as_ref() + .failure_reason(hash) + .await + .context("failed getting failure reason of `setTokenMultiplier` transaction")?; return Err(anyhow::Error::msg(format!( - "`setTokenMultiplier` transaction {:?} failed with status {:?}", + "`setTokenMultiplier` transaction {:?} failed with status {:?}, reason: {:?}", hex::encode(hash), - receipt.status + receipt.status, + reason ))); } else { tokio::time::sleep(sleep_duration).await; From 9d454c44664422858ee7c7a8aaa95a6ede2a01e8 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 00:12:16 +0200 Subject: [PATCH 38/85] feat: check changing base token ratio --- core/tests/ts-integration/tests/fees.test.ts | 81 +++++++++++++++----- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 39bca17e371..129fd9bd6a6 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -188,7 +188,14 @@ testFees('Test fees', () => { test('Test gas price expected value', async () => { const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 2_000_000_000n; /// set to 2 gwei - await setInternalL1GasPrice(alice._providerL2(), l1GasPrice.toString(), l1GasPrice.toString()); + const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); + const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; + + await setInternalL1GasPrice(alice._providerL2(), { + newL1GasPrice: l1GasPrice.toString(), + newPubdataPrice: l1GasPrice.toString(), + customBaseToken: !isETHBasedChain + }); const receipt = await ( await alice.sendTransaction({ @@ -203,8 +210,6 @@ testFees('Test fees', () => { : 110_000_000; // 0.11 gwei, in validium we need to add compute overhead const expectedCustomGasPrice = expectedETHGasPrice * 0.314; - const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); - const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; if (isETHBasedChain) { expect(receipt.gasPrice).toBe(BigInt(expectedETHGasPrice)); } else { @@ -212,6 +217,26 @@ testFees('Test fees', () => { expect(receipt.gasPrice).toBeGreaterThan(expectedCustomGasPrice * 0.85); expect(receipt.gasPrice).toBeLessThan(expectedCustomGasPrice * 1.15); } + + if (!isETHBasedChain) { + await setInternalL1GasPrice(alice._providerL2(), { + newL1GasPrice: l1GasPrice.toString(), + newPubdataPrice: l1GasPrice.toString(), + customBaseToken: true, + forcedBaseTokenPriceNumerator: 271, + forcedBaseTokenPriceDenumerator: 100, + }); + + const receipt2 = await ( + await alice.sendTransaction({ + to: receiver, + value: BigInt(1) + }) + ).wait(); + + const expectedCustomGasPrice = expectedETHGasPrice * 2.71; + expect(receipt2.gasPrice).toBe(BigInt(expectedCustomGasPrice)); + } }); test('Test gas consumption under large L1 gas price', async () => { @@ -234,11 +259,10 @@ testFees('Test fees', () => { // that the gasLimit is indeed over u32::MAX, which is the most important tested property. const requiredPubdataPrice = minimalL2GasPrice * 100_000n; - await setInternalL1GasPrice( - alice._providerL2(), - requiredPubdataPrice.toString(), - requiredPubdataPrice.toString() - ); + await setInternalL1GasPrice(alice._providerL2(), { + newL1GasPrice: requiredPubdataPrice.toString(), + newPubdataPrice: requiredPubdataPrice.toString() + }); const l1Messenger = new ethers.Contract(zksync.utils.L1_MESSENGER_ADDRESS, zksync.utils.L1_MESSENGER, alice); @@ -279,7 +303,7 @@ testFees('Test fees', () => { afterAll(async () => { // Returning the pubdata price to the default one - await setInternalL1GasPrice(alice._providerL2(), undefined, undefined, true); + await setInternalL1GasPrice(alice._providerL2(), { disconnect: true }); await testMaster.deinitialize(); }); @@ -292,8 +316,11 @@ async function appendResults( newL1GasPrice: bigint, reports: string[] ): Promise { - // For the sake of simplicity, we'll use the same pubdata price as the L1 gas price. - await setInternalL1GasPrice(sender._providerL2(), newL1GasPrice.toString(), newL1GasPrice.toString()); + // For the sake of simplicity, we'll use the same pubdata price as the L1 gas prifeesce. + await setInternalL1GasPrice(sender._providerL2(), { + newL1GasPrice: newL1GasPrice.toString(), + newPubdataPrice: newL1GasPrice.toString() + }); if (originalL1Receipts.length !== reports.length && originalL1Receipts.length !== transactionRequests.length) { throw new Error('The array of receipts and reports have different length'); @@ -366,9 +393,14 @@ async function killServerAndWaitForShutdown(provider: zksync.Provider) { async function setInternalL1GasPrice( provider: zksync.Provider, - newL1GasPrice?: string, - newPubdataPrice?: string, - disconnect?: boolean + options: { + newL1GasPrice?: string; + newPubdataPrice?: string; + customBaseToken?: boolean; + forcedBaseTokenPriceNumerator?: number; + forcedBaseTokenPriceDenumerator?: number; + disconnect?: boolean; + } ) { // Make sure server isn't running. try { @@ -377,26 +409,35 @@ async function setInternalL1GasPrice( // Run server in background. let command = 'zk server --components api,tree,eth,state_keeper,da_dispatcher,vm_runner_protective_reads'; + if (options.customBaseToken) command += ',base_token_ratio_persister'; command = `DATABASE_MERKLE_TREE_MODE=full ${command}`; - if (newPubdataPrice) { - command = `ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_PUBDATA_PRICE=${newPubdataPrice} ${command}`; + if (options.newPubdataPrice) { + command = `ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_PUBDATA_PRICE=${options.newPubdataPrice} ${command}`; } - if (newL1GasPrice) { + if (options.newL1GasPrice) { // We need to ensure that each transaction gets into its own batch for more fair comparison. - command = `ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_L1_GAS_PRICE=${newL1GasPrice} ${command}`; + command = `ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_L1_GAS_PRICE=${options.newL1GasPrice} ${command}`; } - const testMode = newPubdataPrice || newL1GasPrice; + const testMode = options.newPubdataPrice || options.newL1GasPrice; if (testMode) { // We need to ensure that each transaction gets into its own batch for more fair comparison. command = `CHAIN_STATE_KEEPER_TRANSACTION_SLOTS=1 ${command}`; } + if (options.forcedBaseTokenPriceNumerator) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=${options.forcedBaseTokenPriceNumerator} ${command}`; + } + + if (options.forcedBaseTokenPriceDenumerator) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.forcedBaseTokenPriceDenumerator} ${command}`; + } + const zkSyncServer = utils.background({ command, stdio: [null, logs, logs] }); - if (disconnect) { + if (options.disconnect) { zkSyncServer.unref(); } From 83dfbeab4d1f7eaa36018766f63418b5cf6a59e7 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 00:15:02 +0200 Subject: [PATCH 39/85] fix: remove fluctuation in base token ratio --- core/tests/ts-integration/tests/base-token.test.ts | 4 +--- core/tests/ts-integration/tests/fees.test.ts | 6 ++---- etc/env/base/external_price_api.toml | 3 +-- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/core/tests/ts-integration/tests/base-token.test.ts b/core/tests/ts-integration/tests/base-token.test.ts index 14c60d43560..f1ec4ff7725 100644 --- a/core/tests/ts-integration/tests/base-token.test.ts +++ b/core/tests/ts-integration/tests/base-token.test.ts @@ -36,9 +36,7 @@ describe('base ERC20 contract checks', () => { const numerator = Number(await zksyncContract.baseTokenGasPriceMultiplierNominator()); const denominator = Number(await zksyncContract.baseTokenGasPriceMultiplierDenominator()); - // checking that the numerator and denominator have appropriate values (there is 10% randomness, so we have 15% tolerance) - expect(numerator).toBeGreaterThan(314 * 0.85); - expect(numerator).toBeLessThan(314 * 1.15); + expect(numerator).toBe(314); expect(denominator).toBe(1000); }); diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 129fd9bd6a6..941b4413e53 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -213,9 +213,7 @@ testFees('Test fees', () => { if (isETHBasedChain) { expect(receipt.gasPrice).toBe(BigInt(expectedETHGasPrice)); } else { - // We need some tolerance here, becouse base token "forced" price provider has 10% randomness in its price - expect(receipt.gasPrice).toBeGreaterThan(expectedCustomGasPrice * 0.85); - expect(receipt.gasPrice).toBeLessThan(expectedCustomGasPrice * 1.15); + expect(receipt.gasPrice).toBe(BigInt(expectedCustomGasPrice)); } if (!isETHBasedChain) { @@ -224,7 +222,7 @@ testFees('Test fees', () => { newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, forcedBaseTokenPriceNumerator: 271, - forcedBaseTokenPriceDenumerator: 100, + forcedBaseTokenPriceDenumerator: 100 }); const receipt2 = await ( diff --git a/etc/env/base/external_price_api.toml b/etc/env/base/external_price_api.toml index cd6fbe4ce69..803ebcae650 100644 --- a/etc/env/base/external_price_api.toml +++ b/etc/env/base/external_price_api.toml @@ -7,5 +7,4 @@ source = "forced" [external_price_api_client.forced] numerator = 314 -denominator = 1000 -fluctuation = 10 \ No newline at end of file +denominator = 1000 \ No newline at end of file From cbe672f22e25b5d394119db3be4ac5d329c13a25 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 17:54:18 +0200 Subject: [PATCH 40/85] feat: add fluctuations test --- core/tests/ts-integration/tests/fees.test.ts | 84 ++++++++++++++++++-- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 941b4413e53..5ff9cd63342 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -221,8 +221,8 @@ testFees('Test fees', () => { newL1GasPrice: l1GasPrice.toString(), newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, - forcedBaseTokenPriceNumerator: 271, - forcedBaseTokenPriceDenumerator: 100 + forcedBaseTokenRatioNumerator: 271, + forcedBaseTokenRatioDenumerator: 100 }); const receipt2 = await ( @@ -237,6 +237,63 @@ testFees('Test fees', () => { } }); + test('Test base token ratio fluctuations', async () => { + const receiver = ethers.Wallet.createRandom().address; + const l1GasPrice = 2_000_000_000n; /// set to 2 gwei + const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); + const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; + + if (isETHBasedChain) return; + + await setInternalL1GasPrice(alice._providerL2(), { + newL1GasPrice: l1GasPrice.toString(), + newPubdataPrice: l1GasPrice.toString(), + customBaseToken: true, + forcedBaseTokenRatioNumerator: 300, + forcedBaseTokenRatioDenumerator: 100, + forcedBaseTokenRatioFluctuationsAmplitude: 20, + forcedBaseTokenRatioFluctuationsFrequencyMs: 1000 + }); + + const beginFeeParams = await alice._providerL2().getFeeParams(); + const mainContract = await alice.getMainContract(); + const beginL1Nominator = await mainContract.baseTokenGasPriceMultiplierNominator(); + let changedL2 = false; + let changedL1 = false; + for (let i = 0; i < 20; i++) { + await utils.sleep(0.5); + const newFeeParams = await alice._providerL2().getFeeParams(); + // we need ts-ignore as FeeParams is missing existing conversion_ratio field + // @ts-ignore + if ( + (newFeeParams.V2['conversion_ratio'].numerator as number) != + (beginFeeParams.V2['conversion_ratio'].numerator as number) + ) { + // @ts-ignore + const diff = + newFeeParams.V2['conversion_ratio'].numerator - beginFeeParams.V2['conversion_ratio'].numerator; + expect(diff).toBeLessThan(25); //25 = 25%*100 + expect(diff).toBeGreaterThan(-25); + changedL2 = true; + break; + } + } + expect(changedL2).toBeTruthy(); + for (let i = 0; i < 20; i++) { + const newL1Nominator = await mainContract.baseTokenGasPriceMultiplierNominator(); + if (newL1Nominator != beginL1Nominator) { + const diff = newL1Nominator - beginL1Nominator; + expect(diff).toBeLessThan(25); //25 = 25%*100 + expect(diff).toBeGreaterThan(-25); + changedL1 = true; + break; + } + await utils.sleep(0.5); + } + + expect(changedL1).toBeTruthy(); + }); + test('Test gas consumption under large L1 gas price', async () => { if (testMaster.environment().l1BatchCommitDataGeneratorMode === DataAvailabityMode.Validium) { // We skip this test for Validium mode, since L1 gas price has little impact on the gasLimit in this mode. @@ -395,8 +452,10 @@ async function setInternalL1GasPrice( newL1GasPrice?: string; newPubdataPrice?: string; customBaseToken?: boolean; - forcedBaseTokenPriceNumerator?: number; - forcedBaseTokenPriceDenumerator?: number; + forcedBaseTokenRatioNumerator?: number; + forcedBaseTokenRatioDenumerator?: number; + forcedBaseTokenRatioFluctuationsAmplitude?: number; + forcedBaseTokenRatioFluctuationsFrequencyMs?: number; disconnect?: boolean; } ) { @@ -425,12 +484,21 @@ async function setInternalL1GasPrice( command = `CHAIN_STATE_KEEPER_TRANSACTION_SLOTS=1 ${command}`; } - if (options.forcedBaseTokenPriceNumerator) { - command = `EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=${options.forcedBaseTokenPriceNumerator} ${command}`; + if (options.forcedBaseTokenRatioNumerator) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=${options.forcedBaseTokenRatioNumerator} ${command}`; + } + + if (options.forcedBaseTokenRatioDenumerator) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.forcedBaseTokenRatioDenumerator} ${command}`; + } + + if (options.forcedBaseTokenRatioFluctuationsAmplitude) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION=${options.forcedBaseTokenRatioFluctuationsAmplitude} ${command}`; } - if (options.forcedBaseTokenPriceDenumerator) { - command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.forcedBaseTokenPriceDenumerator} ${command}`; + if (options.forcedBaseTokenRatioFluctuationsFrequencyMs) { + const cacheUpdateInterval = options.forcedBaseTokenRatioFluctuationsFrequencyMs / 2; + command = `BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS=${cacheUpdateInterval} ${command}`; } const zkSyncServer = utils.background({ command, stdio: [null, logs, logs] }); From 390c0d1b587d02726c9731bd6eba73d35c280cc3 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 17:59:11 +0200 Subject: [PATCH 41/85] fix: undo timer.tick reorder --- .../src/base_token_ratio_persister.rs | 10 +++++----- .../src/base_token_ratio_provider.rs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/node/base_token_adjuster/src/base_token_ratio_persister.rs b/core/node/base_token_adjuster/src/base_token_ratio_persister.rs index 215042907dd..d0c4ed05d3a 100644 --- a/core/node/base_token_adjuster/src/base_token_ratio_persister.rs +++ b/core/node/base_token_adjuster/src/base_token_ratio_persister.rs @@ -59,6 +59,11 @@ impl BaseTokenRatioPersister { let mut timer = tokio::time::interval(self.config.price_polling_interval()); while !*stop_receiver.borrow_and_update() { + tokio::select! { + _ = timer.tick() => { /* continue iterations */ } + _ = stop_receiver.changed() => break, + } + if let Err(err) = self.loop_iteration().await { tracing::warn!( "Error in the base_token_ratio_persister loop interaction {}", @@ -69,11 +74,6 @@ impl BaseTokenRatioPersister { .context("Failed to execute a base_token_ratio_persister loop iteration"); } } - - tokio::select! { - _ = timer.tick() => { /* continue iterations */ } - _ = stop_receiver.changed() => break, - } } tracing::info!("Stop signal received, base_token_ratio_persister is shutting down"); diff --git a/core/node/base_token_adjuster/src/base_token_ratio_provider.rs b/core/node/base_token_adjuster/src/base_token_ratio_provider.rs index f8adf2ee214..e16ea16ff0f 100644 --- a/core/node/base_token_adjuster/src/base_token_ratio_provider.rs +++ b/core/node/base_token_adjuster/src/base_token_ratio_provider.rs @@ -48,13 +48,13 @@ impl DBBaseTokenRatioProvider { let mut timer = tokio::time::interval(self.config.price_cache_update_interval()); while !*stop_receiver.borrow_and_update() { - // TODO(PE-129): Implement latest ratio usability logic. - self.update_latest_price().await?; - tokio::select! { _ = timer.tick() => { /* continue iterations */ } _ = stop_receiver.changed() => break, } + + // TODO(PE-129): Implement latest ratio usability logic. + self.update_latest_price().await?; } tracing::info!("Stop signal received, base_token_ratio_provider is shutting down"); From f38102b68ab44bb55a8473efbeacf6b0552d528c Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 18:06:44 +0200 Subject: [PATCH 42/85] fix: typescript --- core/tests/ts-integration/tests/fees.test.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 5ff9cd63342..ff15147c0f0 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -263,15 +263,16 @@ testFees('Test fees', () => { for (let i = 0; i < 20; i++) { await utils.sleep(0.5); const newFeeParams = await alice._providerL2().getFeeParams(); - // we need ts-ignore as FeeParams is missing existing conversion_ratio field - // @ts-ignore + // we need any as FeeParams is missing existing conversion_ratio field + if ( - (newFeeParams.V2['conversion_ratio'].numerator as number) != - (beginFeeParams.V2['conversion_ratio'].numerator as number) + ((newFeeParams.V2 as any)['conversion_ratio'].numerator as number) != + ((beginFeeParams.V2 as any)['conversion_ratio'].numerator as number) ) { // @ts-ignore const diff = - newFeeParams.V2['conversion_ratio'].numerator - beginFeeParams.V2['conversion_ratio'].numerator; + (newFeeParams.V2 as any)['conversion_ratio'].numerator - + (beginFeeParams.V2 as any)['conversion_ratio'].numerator; expect(diff).toBeLessThan(25); //25 = 25%*100 expect(diff).toBeGreaterThan(-25); changedL2 = true; From 4b00cab4a98bb28f6da2dff27cc92b963893c8a8 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 18:25:44 +0200 Subject: [PATCH 43/85] feat: (re)add reason of setTokenMultiplier tx failure --- .../base_token_adjuster/src/base_token_l1_behaviour.rs | 10 ++++++++-- core/node/external_proof_integration_api/src/lib.rs | 3 +-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/core/node/base_token_adjuster/src/base_token_l1_behaviour.rs b/core/node/base_token_adjuster/src/base_token_l1_behaviour.rs index 0199b06ebd6..ce53f1de87b 100644 --- a/core/node/base_token_adjuster/src/base_token_l1_behaviour.rs +++ b/core/node/base_token_adjuster/src/base_token_l1_behaviour.rs @@ -220,10 +220,16 @@ impl BaseTokenL1Behaviour { if receipt.status == Some(1.into()) { return Ok(receipt.gas_used); } + let reason = (*l1_params.eth_client) + .as_ref() + .failure_reason(hash) + .await + .context("failed getting failure reason of `setTokenMultiplier` transaction")?; return Err(anyhow::Error::msg(format!( - "`setTokenMultiplier` transaction {:?} failed with status {:?}", + "`setTokenMultiplier` transaction {:?} failed with status {:?}, reason: {:?}", hex::encode(hash), - receipt.status + receipt.status, + reason ))); } else { tokio::time::sleep(sleep_duration).await; diff --git a/core/node/external_proof_integration_api/src/lib.rs b/core/node/external_proof_integration_api/src/lib.rs index 4ad8e2595a0..4355896e2a2 100644 --- a/core/node/external_proof_integration_api/src/lib.rs +++ b/core/node/external_proof_integration_api/src/lib.rs @@ -4,8 +4,6 @@ mod middleware; mod processor; mod types; -pub use crate::processor::Processor; - use std::net::SocketAddr; use anyhow::Context; @@ -20,6 +18,7 @@ use tokio::sync::watch; use types::{ExternalProof, ProofGenerationDataResponse}; use zksync_basic_types::L1BatchNumber; +pub use crate::processor::Processor; use crate::{ metrics::{CallOutcome, Method}, middleware::MetricsMiddleware, From 86c74b64fad26cbf4a02ea5fd3110739d7e09745 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 18:31:23 +0200 Subject: [PATCH 44/85] fix: restore debug levels --- etc/env/base/rust.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/env/base/rust.toml b/etc/env/base/rust.toml index 671a930f06c..1bb69374ab1 100644 --- a/etc/env/base/rust.toml +++ b/etc/env/base/rust.toml @@ -10,7 +10,7 @@ zksync_block_reverter=info,\ zksync_commitment_generator=info,\ zksync_node_db_pruner=info,\ zksync_eth_sender=info,\ -zksync_node_fee_model=debug,\ +zksync_node_fee_model=info,\ zksync_node_genesis=info,\ zksync_house_keeper=info,\ zksync_proof_data_handler=info,\ @@ -25,7 +25,7 @@ zksync_metadata_calculator=info,\ zksync_node_sync=info,\ zksync_node_consensus=info,\ zksync_contract_verification_server=info,\ -zksync_node_api_server=debug,\ +zksync_node_api_server=info,\ zksync_tee_verifier_input_producer=info,\ zksync_consensus_bft=info,\ zksync_consensus_network=info,\ From 157aaab841580e33c759fa6ed98f540be10c466a Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 19:15:03 +0200 Subject: [PATCH 45/85] fix --- core/tests/ts-integration/tests/fees.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index ff15147c0f0..2cfebaee2b5 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -238,7 +238,6 @@ testFees('Test fees', () => { }); test('Test base token ratio fluctuations', async () => { - const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 2_000_000_000n; /// set to 2 gwei const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; @@ -280,7 +279,7 @@ testFees('Test fees', () => { } } expect(changedL2).toBeTruthy(); - for (let i = 0; i < 20; i++) { + for (let i = 0; i < 40; i++) { const newL1Nominator = await mainContract.baseTokenGasPriceMultiplierNominator(); if (newL1Nominator != beginL1Nominator) { const diff = newL1Nominator - beginL1Nominator; From d322e6eca85ef07241644b545e5c63fad7e62133 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 30 Aug 2024 19:21:28 +0200 Subject: [PATCH 46/85] fix test --- core/tests/ts-integration/tests/fees.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 2cfebaee2b5..e49c4ec4c16 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -272,8 +272,8 @@ testFees('Test fees', () => { const diff = (newFeeParams.V2 as any)['conversion_ratio'].numerator - (beginFeeParams.V2 as any)['conversion_ratio'].numerator; - expect(diff).toBeLessThan(25); //25 = 25%*100 - expect(diff).toBeGreaterThan(-25); + expect(diff).toBeLessThan(75); //75 = 25%*300 + expect(diff).toBeGreaterThan(-75); changedL2 = true; break; } @@ -283,8 +283,8 @@ testFees('Test fees', () => { const newL1Nominator = await mainContract.baseTokenGasPriceMultiplierNominator(); if (newL1Nominator != beginL1Nominator) { const diff = newL1Nominator - beginL1Nominator; - expect(diff).toBeLessThan(25); //25 = 25%*100 - expect(diff).toBeGreaterThan(-25); + expect(diff).toBeLessThan(75); //75 = 25%*300 + expect(diff).toBeGreaterThan(-75); changedL1 = true; break; } From 02f13c02ad4c3eef448bc4c9028db4076b5ae83e Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 13:10:33 +0200 Subject: [PATCH 47/85] fix: update config for zk_toolbox --- etc/env/file_based/general.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 19921cf536c..4a487bbf364 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -297,8 +297,8 @@ base_token_adjuster: external_price_api_client: source: "forced" client_timeout_ms: 10000 - forced_numerator: 3 - forced_denominator: 2 + forced_numerator: 314 + forced_denominator: 1000 house_keeper: From a625f1726ed283b569e363a86a3f0815588da8c3 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 13:10:54 +0200 Subject: [PATCH 48/85] fix: allow more time for L1 update --- core/tests/ts-integration/tests/fees.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index e49c4ec4c16..6ba20f2a2a5 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -279,7 +279,7 @@ testFees('Test fees', () => { } } expect(changedL2).toBeTruthy(); - for (let i = 0; i < 40; i++) { + for (let i = 0; i < 60; i++) { const newL1Nominator = await mainContract.baseTokenGasPriceMultiplierNominator(); if (newL1Nominator != beginL1Nominator) { const diff = newL1Nominator - beginL1Nominator; From a9d6d44b6d27e5a75b8d7e6528a1daed114ddbfb Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 13:17:20 +0200 Subject: [PATCH 49/85] fix: lower base ratio l1 update minimal deviation in tests --- core/tests/ts-integration/tests/fees.test.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 6ba20f2a2a5..ce55e5ee693 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -251,7 +251,8 @@ testFees('Test fees', () => { forcedBaseTokenRatioNumerator: 300, forcedBaseTokenRatioDenumerator: 100, forcedBaseTokenRatioFluctuationsAmplitude: 20, - forcedBaseTokenRatioFluctuationsFrequencyMs: 1000 + forcedBaseTokenRatioFluctuationsFrequencyMs: 1000, + baseTokenAdjusterL1UpdateDeviationPercentage: 0 }); const beginFeeParams = await alice._providerL2().getFeeParams(); @@ -456,6 +457,7 @@ async function setInternalL1GasPrice( forcedBaseTokenRatioDenumerator?: number; forcedBaseTokenRatioFluctuationsAmplitude?: number; forcedBaseTokenRatioFluctuationsFrequencyMs?: number; + baseTokenAdjusterL1UpdateDeviationPercentage?: number; disconnect?: boolean; } ) { @@ -501,6 +503,10 @@ async function setInternalL1GasPrice( command = `BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS=${cacheUpdateInterval} ${command}`; } + if (options.baseTokenAdjusterL1UpdateDeviationPercentage) { + command = `BASE_TOKEN_ADJUSTER_L1_UPDATE_DEVIATION_PERCENTAGE=${options.baseTokenAdjusterL1UpdateDeviationPercentage} ${command}`; + } + const zkSyncServer = utils.background({ command, stdio: [null, logs, logs] }); if (options.disconnect) { From d406c8f7b2eb7a3f81cd8aff557bdd9d11366a02 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 14:57:05 +0200 Subject: [PATCH 50/85] fix: typo --- core/tests/ts-integration/tests/fees.test.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index ce55e5ee693..a152d5b5ebe 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -222,7 +222,7 @@ testFees('Test fees', () => { newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, forcedBaseTokenRatioNumerator: 271, - forcedBaseTokenRatioDenumerator: 100 + forcedBaseTokenRatioDenominator: 100 }); const receipt2 = await ( @@ -249,7 +249,7 @@ testFees('Test fees', () => { newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, forcedBaseTokenRatioNumerator: 300, - forcedBaseTokenRatioDenumerator: 100, + forcedBaseTokenRatioDenominator: 100, forcedBaseTokenRatioFluctuationsAmplitude: 20, forcedBaseTokenRatioFluctuationsFrequencyMs: 1000, baseTokenAdjusterL1UpdateDeviationPercentage: 0 @@ -280,7 +280,7 @@ testFees('Test fees', () => { } } expect(changedL2).toBeTruthy(); - for (let i = 0; i < 60; i++) { + for (let i = 0; i < 10; i++) { const newL1Nominator = await mainContract.baseTokenGasPriceMultiplierNominator(); if (newL1Nominator != beginL1Nominator) { const diff = newL1Nominator - beginL1Nominator; @@ -454,7 +454,7 @@ async function setInternalL1GasPrice( newPubdataPrice?: string; customBaseToken?: boolean; forcedBaseTokenRatioNumerator?: number; - forcedBaseTokenRatioDenumerator?: number; + forcedBaseTokenRatioDenominator?: number; forcedBaseTokenRatioFluctuationsAmplitude?: number; forcedBaseTokenRatioFluctuationsFrequencyMs?: number; baseTokenAdjusterL1UpdateDeviationPercentage?: number; @@ -490,8 +490,8 @@ async function setInternalL1GasPrice( command = `EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=${options.forcedBaseTokenRatioNumerator} ${command}`; } - if (options.forcedBaseTokenRatioDenumerator) { - command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.forcedBaseTokenRatioDenumerator} ${command}`; + if (options.forcedBaseTokenRatioDenominator) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.forcedBaseTokenRatioDenominator} ${command}`; } if (options.forcedBaseTokenRatioFluctuationsAmplitude) { From fa62583dfd22bf3e7827ba9a1bdd8070480db20e Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 15:28:32 +0200 Subject: [PATCH 51/85] fix: properly set l1 update deviation percentage --- core/tests/ts-integration/tests/fees.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index a152d5b5ebe..5e6b40ef0ef 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -471,11 +471,11 @@ async function setInternalL1GasPrice( if (options.customBaseToken) command += ',base_token_ratio_persister'; command = `DATABASE_MERKLE_TREE_MODE=full ${command}`; - if (options.newPubdataPrice) { + if (options.newPubdataPrice !== undefined) { command = `ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_PUBDATA_PRICE=${options.newPubdataPrice} ${command}`; } - if (options.newL1GasPrice) { + if (options.newL1GasPrice !== undefined) { // We need to ensure that each transaction gets into its own batch for more fair comparison. command = `ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_L1_GAS_PRICE=${options.newL1GasPrice} ${command}`; } @@ -486,24 +486,24 @@ async function setInternalL1GasPrice( command = `CHAIN_STATE_KEEPER_TRANSACTION_SLOTS=1 ${command}`; } - if (options.forcedBaseTokenRatioNumerator) { + if (options.forcedBaseTokenRatioNumerator !== undefined) { command = `EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=${options.forcedBaseTokenRatioNumerator} ${command}`; } - if (options.forcedBaseTokenRatioDenominator) { + if (options.forcedBaseTokenRatioDenominator !== undefined) { command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.forcedBaseTokenRatioDenominator} ${command}`; } - if (options.forcedBaseTokenRatioFluctuationsAmplitude) { + if (options.forcedBaseTokenRatioFluctuationsAmplitude !== undefined) { command = `EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION=${options.forcedBaseTokenRatioFluctuationsAmplitude} ${command}`; } - if (options.forcedBaseTokenRatioFluctuationsFrequencyMs) { + if (options.forcedBaseTokenRatioFluctuationsFrequencyMs !== undefined) { const cacheUpdateInterval = options.forcedBaseTokenRatioFluctuationsFrequencyMs / 2; command = `BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS=${cacheUpdateInterval} ${command}`; } - if (options.baseTokenAdjusterL1UpdateDeviationPercentage) { + if (options.baseTokenAdjusterL1UpdateDeviationPercentage !== undefined) { command = `BASE_TOKEN_ADJUSTER_L1_UPDATE_DEVIATION_PERCENTAGE=${options.baseTokenAdjusterL1UpdateDeviationPercentage} ${command}`; } From 6f9e6ba5ea6356875a32a46510ed46fbab9b3fa8 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 15:30:53 +0200 Subject: [PATCH 52/85] fix: zk_toolbox env for tests --- etc/env/file_based/general.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 4a487bbf364..217a3a536cc 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -297,8 +297,9 @@ base_token_adjuster: external_price_api_client: source: "forced" client_timeout_ms: 10000 - forced_numerator: 314 - forced_denominator: 1000 + forced: + numerator: 314 + denominator: 1000 house_keeper: From eeea10c201fe50778d9d4fe92535ace46914ba92 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 16:09:27 +0200 Subject: [PATCH 53/85] feat: remove unnecessery transfer of extra funds in fees.test.ts --- core/tests/ts-integration/tests/fees.test.ts | 40 -------------------- 1 file changed, 40 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 5e6b40ef0ef..ac46daed766 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -62,46 +62,6 @@ testFees('Test fees', () => { tokenDetails = testMaster.environment().erc20Token; aliceErc20 = new ethers.Contract(tokenDetails.l1Address, zksync.utils.IERC20, alice.ethWallet()); - - const mainWallet = new zksync.Wallet( - testMaster.environment().mainWalletPK, - alice._providerL2(), - alice._providerL1() - ); - - const bridgehub = await mainWallet.getBridgehubContract(); - const chainId = testMaster.environment().l2ChainId; - const baseTokenAddress = await bridgehub.baseToken(chainId); - - console.log(`Alice address ${alice.address}. Main wallet address: ${mainWallet.address}`); - console.log( - `Before deposit: Alice balance ${ethers.formatEther( - await alice.getBalance() - )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` - ); - const depositTx = await mainWallet.deposit({ - token: baseTokenAddress, - amount: ethers.parseEther('100'), - approveERC20: true, - approveBaseERC20: true - }); - await depositTx.wait(); - await Promise.all( - await sendTransfers( - zksync.utils.ETH_ADDRESS, - mainWallet, - { alice: alice.privateKey }, - ethers.parseEther('100'), - undefined, - undefined, - new Reporter() - ) - ); - console.log( - `After deposit: Alice balance ${ethers.formatEther( - await alice.getBalance() - )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` - ); }); test('Test fees', async () => { From d5512cd567f6010ab6e8317ec538fa702b3c95e2 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 16:24:21 +0200 Subject: [PATCH 54/85] fix: lint --- core/tests/ts-integration/tests/fees.test.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index ac46daed766..cdeb1e3753b 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -17,8 +17,6 @@ import * as zksync from 'zksync-ethers'; import * as ethers from 'ethers'; import { DataAvailabityMode, Token } from '../src/types'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; -import { sendTransfers } from '../src/context-owner'; -import { Reporter } from '../src/reporter'; const UINT32_MAX = 2n ** 32n - 1n; const MAX_GAS_PER_PUBDATA = 50_000n; From e4fe076d39640dc88996d4fb36118e196a11371f Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 2 Sep 2024 16:54:05 +0200 Subject: [PATCH 55/85] fix: properly set zk_toolbox base token price --- .github/workflows/ci-zk-toolbox-reusable.yml | 4 ++-- etc/env/file_based/general.yaml | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-zk-toolbox-reusable.yml b/.github/workflows/ci-zk-toolbox-reusable.yml index 5e9402b69ea..d18e45c279d 100644 --- a/.github/workflows/ci-zk-toolbox-reusable.yml +++ b/.github/workflows/ci-zk-toolbox-reusable.yml @@ -87,8 +87,8 @@ jobs: --wallet-creation localhost \ --l1-batch-commit-data-generator-mode rollup \ --base-token-address ${{ env.address }} \ - --base-token-price-nominator 3 \ - --base-token-price-denominator 2 \ + --base-token-price-nominator 314 \ + --base-token-price-denominator 1000 \ --set-as-default false \ --ignore-prerequisites diff --git a/etc/env/file_based/general.yaml b/etc/env/file_based/general.yaml index 217a3a536cc..4a487bbf364 100644 --- a/etc/env/file_based/general.yaml +++ b/etc/env/file_based/general.yaml @@ -297,9 +297,8 @@ base_token_adjuster: external_price_api_client: source: "forced" client_timeout_ms: 10000 - forced: - numerator: 314 - denominator: 1000 + forced_numerator: 314 + forced_denominator: 1000 house_keeper: From ea7a3b7940404d490ddae4ca9b84089e79c26ae5 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 3 Sep 2024 10:04:15 +0200 Subject: [PATCH 56/85] Revert "feat: remove unnecessery transfer of extra funds in fees.test.ts" This reverts commit eeea10c201fe50778d9d4fe92535ace46914ba92. --- core/tests/ts-integration/tests/fees.test.ts | 40 ++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index cdeb1e3753b..ad885b617fe 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -60,6 +60,46 @@ testFees('Test fees', () => { tokenDetails = testMaster.environment().erc20Token; aliceErc20 = new ethers.Contract(tokenDetails.l1Address, zksync.utils.IERC20, alice.ethWallet()); + + const mainWallet = new zksync.Wallet( + testMaster.environment().mainWalletPK, + alice._providerL2(), + alice._providerL1() + ); + + const bridgehub = await mainWallet.getBridgehubContract(); + const chainId = testMaster.environment().l2ChainId; + const baseTokenAddress = await bridgehub.baseToken(chainId); + + console.log(`Alice address ${alice.address}. Main wallet address: ${mainWallet.address}`); + console.log( + `Before deposit: Alice balance ${ethers.formatEther( + await alice.getBalance() + )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` + ); + const depositTx = await mainWallet.deposit({ + token: baseTokenAddress, + amount: ethers.parseEther('100'), + approveERC20: true, + approveBaseERC20: true + }); + await depositTx.wait(); + await Promise.all( + await sendTransfers( + zksync.utils.ETH_ADDRESS, + mainWallet, + { alice: alice.privateKey }, + ethers.parseEther('100'), + undefined, + undefined, + new Reporter() + ) + ); + console.log( + `After deposit: Alice balance ${ethers.formatEther( + await alice.getBalance() + )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` + ); }); test('Test fees', async () => { From 2722b79c7e29eb4a754ca4fc911534159bbb3679 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 3 Sep 2024 11:25:09 +0200 Subject: [PATCH 57/85] fix: missing import, remove extra logs --- core/tests/ts-integration/tests/fees.test.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index ad885b617fe..7ba9dcb1a65 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -17,6 +17,8 @@ import * as zksync from 'zksync-ethers'; import * as ethers from 'ethers'; import { DataAvailabityMode, Token } from '../src/types'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; +import { sendTransfers } from '../src/context-owner'; +import { Reporter } from '../src/reporter'; const UINT32_MAX = 2n ** 32n - 1n; const MAX_GAS_PER_PUBDATA = 50_000n; @@ -71,12 +73,6 @@ testFees('Test fees', () => { const chainId = testMaster.environment().l2ChainId; const baseTokenAddress = await bridgehub.baseToken(chainId); - console.log(`Alice address ${alice.address}. Main wallet address: ${mainWallet.address}`); - console.log( - `Before deposit: Alice balance ${ethers.formatEther( - await alice.getBalance() - )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` - ); const depositTx = await mainWallet.deposit({ token: baseTokenAddress, amount: ethers.parseEther('100'), @@ -95,11 +91,6 @@ testFees('Test fees', () => { new Reporter() ) ); - console.log( - `After deposit: Alice balance ${ethers.formatEther( - await alice.getBalance() - )}. Main wallet balance: ${ethers.formatEther(await mainWallet.getBalance())}` - ); }); test('Test fees', async () => { From d212602a3ba28ce7f35a6aff3c3e635b234f00f2 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 3 Sep 2024 15:10:04 +0200 Subject: [PATCH 58/85] feat: add config option for fluctuation --- .../src/configs/external_price_api_client.rs | 14 ++++++++++++-- core/lib/config/src/testonly.rs | 1 + .../env_config/src/external_price_api_client.rs | 1 + .../src/forced_price_client.rs | 17 +++++++++++------ .../src/external_price_api_client.rs | 5 +++++ .../config/external_price_api_client.proto | 1 + 6 files changed, 31 insertions(+), 8 deletions(-) diff --git a/core/lib/config/src/configs/external_price_api_client.rs b/core/lib/config/src/configs/external_price_api_client.rs index 15cc7d29d84..96cf22cf0df 100644 --- a/core/lib/config/src/configs/external_price_api_client.rs +++ b/core/lib/config/src/configs/external_price_api_client.rs @@ -4,16 +4,22 @@ use serde::Deserialize; pub const DEFAULT_TIMEOUT_MS: u64 = 10_000; +pub const DEFAULT_FORCED_NEXT_VALUE_FLUCTUATION: u32 = 3; + #[derive(Debug, Clone, PartialEq, Deserialize)] pub struct ForcedPriceClientConfig { /// Forced conversion ratio pub numerator: Option, pub denominator: Option, - /// Forced fluctuation. It defines how much percent numerator / - /// denominator should fluctuate from their forced values. If it's None or 0, then ForcedPriceClient + /// Forced fluctuation. It defines how much percent the ratio + /// should fluctuate from their forced values. If it's None or 0, then ForcedPriceClient /// will return the same quote every time it's called. Otherwise, ForcedPriceClient will return /// forced_quote +/- forced_fluctuation % from its values. pub fluctuation: Option, + /// In order to smoothe out fluctuation consecutive values returned by forced client will not + /// differ more than next_value_fluctuation percent. If it's None, a default of 3% will be applied. + #[serde(default = "ExternalPriceApiClientConfig::default_forced_next_value_fluctuation")] + pub next_value_fluctuation: u32, } #[derive(Debug, Clone, PartialEq, Deserialize)] @@ -31,6 +37,10 @@ impl ExternalPriceApiClientConfig { DEFAULT_TIMEOUT_MS } + fn default_forced_next_value_fluctuation() -> u32 { + DEFAULT_FORCED_NEXT_VALUE_FLUCTUATION + } + pub fn client_timeout(&self) -> Duration { Duration::from_millis(self.client_timeout_ms) } diff --git a/core/lib/config/src/testonly.rs b/core/lib/config/src/testonly.rs index 8c713319a5e..0318edf85e4 100644 --- a/core/lib/config/src/testonly.rs +++ b/core/lib/config/src/testonly.rs @@ -1081,6 +1081,7 @@ impl Distribution, fluctuation: Option, + next_value_fluctuation: u32, } impl ForcedPriceClient { @@ -36,6 +35,9 @@ impl ForcedPriceClient { let fluctuation = forced_price_client_config .fluctuation .map(|x| x.clamp(0, 100)); + let next_value_fluctuation = forced_price_client_config + .next_value_fluctuation + .clamp(0, 100); Self { ratio: BaseTokenAPIRatio { @@ -45,6 +47,7 @@ impl ForcedPriceClient { }, previous_numerator: RwLock::new(NonZeroU64::new(numerator).unwrap()), fluctuation, + next_value_fluctuation, } } } @@ -61,14 +64,16 @@ impl PriceAPIClient for ForcedPriceClient { max( (self.ratio.numerator.get() as f64 * (1.0 - (fluctation as f64 / 100.0))) .round() as u64, - (previous_numerator.get() as f64 * (1.0 - NEXT_VALUE_VARIATION_RANGE)).round() - as u64, + (previous_numerator.get() as f64 + * (1.0 - (self.next_value_fluctuation as f64 / 100.0))) + .round() as u64, ), min( (self.ratio.numerator.get() as f64 * (1.0 + (fluctation as f64 / 100.0))) .round() as u64, - (previous_numerator.get() as f64 * (1.0 + NEXT_VALUE_VARIATION_RANGE)).round() - as u64, + (previous_numerator.get() as f64 + * (1.0 + (self.next_value_fluctuation as f64 / 100.0))) + .round() as u64, ), ); diff --git a/core/lib/protobuf_config/src/external_price_api_client.rs b/core/lib/protobuf_config/src/external_price_api_client.rs index e5ed809a128..dbc341c1865 100644 --- a/core/lib/protobuf_config/src/external_price_api_client.rs +++ b/core/lib/protobuf_config/src/external_price_api_client.rs @@ -17,6 +17,9 @@ impl ProtoRepr for proto::ExternalPriceApiClient { numerator: self.forced_numerator, denominator: self.forced_denominator, fluctuation: self.forced_fluctuation, + next_value_fluctuation: self.forced_next_value_fluctuation.unwrap_or( + configs::external_price_api_client::DEFAULT_FORCED_NEXT_VALUE_FLUCTUATION, + ), }), }, ) @@ -26,6 +29,7 @@ impl ProtoRepr for proto::ExternalPriceApiClient { let numerator = this.forced.as_ref().and_then(|x| x.numerator); let denominator = this.forced.as_ref().and_then(|x| x.denominator); let fluctuation = this.forced.as_ref().and_then(|x| x.fluctuation); + let next_value_fluctuation = this.forced.as_ref().map(|x| x.next_value_fluctuation); Self { source: Some(this.source.clone()), @@ -35,6 +39,7 @@ impl ProtoRepr for proto::ExternalPriceApiClient { forced_numerator: numerator, forced_denominator: denominator, forced_fluctuation: fluctuation, + forced_next_value_fluctuation: next_value_fluctuation, } } } diff --git a/core/lib/protobuf_config/src/proto/config/external_price_api_client.proto b/core/lib/protobuf_config/src/proto/config/external_price_api_client.proto index 646bcfbd764..63f3233c575 100644 --- a/core/lib/protobuf_config/src/proto/config/external_price_api_client.proto +++ b/core/lib/protobuf_config/src/proto/config/external_price_api_client.proto @@ -10,4 +10,5 @@ message ExternalPriceApiClient { optional uint64 forced_numerator = 5; optional uint64 forced_denominator = 6; optional uint32 forced_fluctuation = 7; + optional uint32 forced_next_value_fluctuation = 8; } From 88154febc97819838ad8cfbf1122faa3187f8e38 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 3 Sep 2024 16:57:43 +0200 Subject: [PATCH 59/85] fix: config test --- core/lib/env_config/src/external_price_api_client.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/lib/env_config/src/external_price_api_client.rs b/core/lib/env_config/src/external_price_api_client.rs index 2541e3fc379..07ab40e059d 100644 --- a/core/lib/env_config/src/external_price_api_client.rs +++ b/core/lib/env_config/src/external_price_api_client.rs @@ -43,7 +43,7 @@ mod tests { numerator: Some(100), denominator: Some(1), fluctuation: Some(10), - next_value_fluctuation: 2, + next_value_fluctuation: 1, }), } } @@ -58,6 +58,7 @@ mod tests { EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=100 EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=1 EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION=10 + EXTERNAL_PRICE_API_CLIENT_FORCED_NEXT_VALUE_FLUCTUATION=1 "#; lock.set_env(config); From 3ad4d86842d1f613c679317317b42413b7019356 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 3 Sep 2024 17:46:50 +0200 Subject: [PATCH 60/85] feat: properly perform fluctuations on low numerator --- .../src/forced_price_client.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index e5731fe93dc..18bcfb01219 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -39,12 +39,23 @@ impl ForcedPriceClient { .next_value_fluctuation .clamp(0, 100); - Self { - ratio: BaseTokenAPIRatio { + let ratio = if numerator < 100 && fluctuation.is_some_and(|f| f > 0) { + // If numerator is too small we need to multiply by 100 to make sure fluctuations can be applied + BaseTokenAPIRatio { + numerator: NonZeroU64::new(numerator * 100).unwrap(), + denominator: NonZeroU64::new(denominator * 100).unwrap(), + ratio_timestamp: chrono::Utc::now(), + } + } else { + BaseTokenAPIRatio { numerator: NonZeroU64::new(numerator).unwrap(), denominator: NonZeroU64::new(denominator).unwrap(), ratio_timestamp: chrono::Utc::now(), - }, + } + }; + + Self { + ratio, previous_numerator: RwLock::new(NonZeroU64::new(numerator).unwrap()), fluctuation, next_value_fluctuation, From 7e1997df3befa9c16d264ec7ee5c78ead722061f Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 6 Sep 2024 16:27:03 +0200 Subject: [PATCH 61/85] fix: typo --- core/lib/config/src/configs/external_price_api_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib/config/src/configs/external_price_api_client.rs b/core/lib/config/src/configs/external_price_api_client.rs index 96cf22cf0df..e52d0fb70d6 100644 --- a/core/lib/config/src/configs/external_price_api_client.rs +++ b/core/lib/config/src/configs/external_price_api_client.rs @@ -16,7 +16,7 @@ pub struct ForcedPriceClientConfig { /// will return the same quote every time it's called. Otherwise, ForcedPriceClient will return /// forced_quote +/- forced_fluctuation % from its values. pub fluctuation: Option, - /// In order to smoothe out fluctuation consecutive values returned by forced client will not + /// In order to smooth out fluctuation consecutive values returned by forced client will not /// differ more than next_value_fluctuation percent. If it's None, a default of 3% will be applied. #[serde(default = "ExternalPriceApiClientConfig::default_forced_next_value_fluctuation")] pub next_value_fluctuation: u32, From 2384d62e1b89eb5e1675ba93955eaeb89c4629ee Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 6 Sep 2024 16:31:05 +0200 Subject: [PATCH 62/85] fix: only deposit extra funds in custom base token test --- core/tests/ts-integration/tests/fees.test.ts | 45 ++++++++++---------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 7ba9dcb1a65..ecacd8d1ab1 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -55,6 +55,7 @@ testFees('Test fees', () => { let tokenDetails: Token; let aliceErc20: zksync.Contract; + let isETHBasedChain: boolean; beforeAll(async () => { testMaster = TestMaster.getInstance(__filename); @@ -72,25 +73,29 @@ testFees('Test fees', () => { const bridgehub = await mainWallet.getBridgehubContract(); const chainId = testMaster.environment().l2ChainId; const baseTokenAddress = await bridgehub.baseToken(chainId); + isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; - const depositTx = await mainWallet.deposit({ - token: baseTokenAddress, - amount: ethers.parseEther('100'), - approveERC20: true, - approveBaseERC20: true - }); - await depositTx.wait(); - await Promise.all( - await sendTransfers( - zksync.utils.ETH_ADDRESS, - mainWallet, - { alice: alice.privateKey }, - ethers.parseEther('100'), - undefined, - undefined, - new Reporter() - ) - ); + // On non ETH based chains the standard deposit is not enough to run all this tests + if (!isETHBasedChain) { + const depositTx = await mainWallet.deposit({ + token: baseTokenAddress, + amount: ethers.parseEther('100'), + approveERC20: true, + approveBaseERC20: true + }); + await depositTx.wait(); + await Promise.all( + await sendTransfers( + zksync.utils.ETH_ADDRESS, + mainWallet, + {alice: alice.privateKey}, + ethers.parseEther('100'), + undefined, + undefined, + new Reporter() + ) + ); + } }); test('Test fees', async () => { @@ -177,8 +182,6 @@ testFees('Test fees', () => { test('Test gas price expected value', async () => { const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 2_000_000_000n; /// set to 2 gwei - const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); - const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; await setInternalL1GasPrice(alice._providerL2(), { newL1GasPrice: l1GasPrice.toString(), @@ -228,8 +231,6 @@ testFees('Test fees', () => { test('Test base token ratio fluctuations', async () => { const l1GasPrice = 2_000_000_000n; /// set to 2 gwei - const baseTokenAddress = await alice._providerL2().getBaseTokenContractAddress(); - const isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; if (isETHBasedChain) return; From 8680ed85e09434bb5b11785343d9e1ef011137b1 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 6 Sep 2024 16:35:21 +0200 Subject: [PATCH 63/85] fix: naming and docs in fees.test.ts --- core/tests/ts-integration/tests/fees.test.ts | 46 ++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index ecacd8d1ab1..31a6aad3eda 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -88,7 +88,7 @@ testFees('Test fees', () => { await sendTransfers( zksync.utils.ETH_ADDRESS, mainWallet, - {alice: alice.privateKey}, + { alice: alice.privateKey }, ethers.parseEther('100'), undefined, undefined, @@ -213,8 +213,8 @@ testFees('Test fees', () => { newL1GasPrice: l1GasPrice.toString(), newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, - forcedBaseTokenRatioNumerator: 271, - forcedBaseTokenRatioDenominator: 100 + externalPriceApiClientForcedNumerator: 271, + externalPriceApiClientForcedDenominator: 100 }); const receipt2 = await ( @@ -238,10 +238,10 @@ testFees('Test fees', () => { newL1GasPrice: l1GasPrice.toString(), newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, - forcedBaseTokenRatioNumerator: 300, - forcedBaseTokenRatioDenominator: 100, - forcedBaseTokenRatioFluctuationsAmplitude: 20, - forcedBaseTokenRatioFluctuationsFrequencyMs: 1000, + externalPriceApiClientForcedNumerator: 300, + externalPriceApiClientForcedDenominator: 100, + externalPriceApiClientForcedFluctuation: 20, + baseTokenPricePoolingIntervalMs: 1000, baseTokenAdjusterL1UpdateDeviationPercentage: 0 }); @@ -263,7 +263,8 @@ testFees('Test fees', () => { const diff = (newFeeParams.V2 as any)['conversion_ratio'].numerator - (beginFeeParams.V2 as any)['conversion_ratio'].numerator; - expect(diff).toBeLessThan(75); //75 = 25%*300 + // Deviation is 20%, Adding 5% extra for any arithmetic precision issues, 25%*300 = 75 + expect(diff).toBeLessThan(75); expect(diff).toBeGreaterThan(-75); changedL2 = true; break; @@ -274,7 +275,7 @@ testFees('Test fees', () => { const newL1Nominator = await mainContract.baseTokenGasPriceMultiplierNominator(); if (newL1Nominator != beginL1Nominator) { const diff = newL1Nominator - beginL1Nominator; - expect(diff).toBeLessThan(75); //75 = 25%*300 + expect(diff).toBeLessThan(75); // as above expect(diff).toBeGreaterThan(-75); changedL1 = true; break; @@ -443,10 +444,10 @@ async function setInternalL1GasPrice( newL1GasPrice?: string; newPubdataPrice?: string; customBaseToken?: boolean; - forcedBaseTokenRatioNumerator?: number; - forcedBaseTokenRatioDenominator?: number; - forcedBaseTokenRatioFluctuationsAmplitude?: number; - forcedBaseTokenRatioFluctuationsFrequencyMs?: number; + externalPriceApiClientForcedNumerator?: number; + externalPriceApiClientForcedDenominator?: number; + externalPriceApiClientForcedFluctuation?: number; + baseTokenPricePoolingIntervalMs?: number; baseTokenAdjusterL1UpdateDeviationPercentage?: number; disconnect?: boolean; } @@ -476,21 +477,22 @@ async function setInternalL1GasPrice( command = `CHAIN_STATE_KEEPER_TRANSACTION_SLOTS=1 ${command}`; } - if (options.forcedBaseTokenRatioNumerator !== undefined) { - command = `EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=${options.forcedBaseTokenRatioNumerator} ${command}`; + if (options.externalPriceApiClientForcedNumerator !== undefined) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR=${options.externalPriceApiClientForcedNumerator} ${command}`; } - if (options.forcedBaseTokenRatioDenominator !== undefined) { - command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.forcedBaseTokenRatioDenominator} ${command}`; + if (options.externalPriceApiClientForcedDenominator !== undefined) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR=${options.externalPriceApiClientForcedDenominator} ${command}`; } - if (options.forcedBaseTokenRatioFluctuationsAmplitude !== undefined) { - command = `EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION=${options.forcedBaseTokenRatioFluctuationsAmplitude} ${command}`; + if (options.externalPriceApiClientForcedFluctuation !== undefined) { + command = `EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION=${options.externalPriceApiClientForcedFluctuation} ${command}`; } - if (options.forcedBaseTokenRatioFluctuationsFrequencyMs !== undefined) { - const cacheUpdateInterval = options.forcedBaseTokenRatioFluctuationsFrequencyMs / 2; - command = `BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS=${options.forcedBaseTokenRatioFluctuationsFrequencyMs} BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS=${cacheUpdateInterval} ${command}`; + if (options.baseTokenPricePoolingIntervalMs !== undefined) { + const cacheUpdateInterval = options.baseTokenPricePoolingIntervalMs / 2; + // To reduce price polling interval we also need to reduce base token receipt checking and tx sending sleeps as they are blocking the poller. Also cache update needs to be reduced appropriately. + command = `BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS=${options.baseTokenPricePoolingIntervalMs} BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS=${options.baseTokenPricePoolingIntervalMs} BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS=${options.baseTokenPricePoolingIntervalMs} BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS=${cacheUpdateInterval} ${command}`; } if (options.baseTokenAdjusterL1UpdateDeviationPercentage !== undefined) { From 034f720c8c611ec7157d765d31f9670cb65b59ac Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 11 Sep 2024 13:07:45 +0200 Subject: [PATCH 64/85] fix: comments --- core/lib/config/src/configs/external_price_api_client.rs | 9 ++++----- core/lib/external_price_api/src/forced_price_client.rs | 3 +-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/core/lib/config/src/configs/external_price_api_client.rs b/core/lib/config/src/configs/external_price_api_client.rs index e52d0fb70d6..c1092f3a727 100644 --- a/core/lib/config/src/configs/external_price_api_client.rs +++ b/core/lib/config/src/configs/external_price_api_client.rs @@ -11,12 +11,11 @@ pub struct ForcedPriceClientConfig { /// Forced conversion ratio pub numerator: Option, pub denominator: Option, - /// Forced fluctuation. It defines how much percent the ratio - /// should fluctuate from their forced values. If it's None or 0, then ForcedPriceClient - /// will return the same quote every time it's called. Otherwise, ForcedPriceClient will return - /// forced_quote +/- forced_fluctuation % from its values. + /// Forced fluctuation. It defines how much percent the ratio should fluctuate from its forced + /// value. If it's None or 0, then the ForcedPriceClient will return the same quote every time + /// it's called. Otherwise, ForcedPriceClient will return quote with numerator +/- fluctuation %. pub fluctuation: Option, - /// In order to smooth out fluctuation consecutive values returned by forced client will not + /// In order to smooth out fluctuation, consecutive values returned by forced client will not /// differ more than next_value_fluctuation percent. If it's None, a default of 3% will be applied. #[serde(default = "ExternalPriceApiClientConfig::default_forced_next_value_fluctuation")] pub next_value_fluctuation: u32, diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index 18bcfb01219..829c6c11495 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -65,8 +65,7 @@ impl ForcedPriceClient { #[async_trait] impl PriceAPIClient for ForcedPriceClient { - /// Returns a ratio which is 10% higher or lower than the configured forced ratio, - /// but not different more than 3% than the last value + /// Returns the configured ratio with fluctuation applied if enabled async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { if let Some(fluctation) = self.fluctuation { let mut previous_numerator = self.previous_numerator.write().await; From 8bee1d8d2de1f9d56a4b383801cf882daec31cc3 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 11 Sep 2024 13:17:55 +0200 Subject: [PATCH 65/85] fix: RwLock->Mutex --- core/lib/external_price_api/src/forced_price_client.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/lib/external_price_api/src/forced_price_client.rs b/core/lib/external_price_api/src/forced_price_client.rs index 829c6c11495..cca2e7cce2a 100644 --- a/core/lib/external_price_api/src/forced_price_client.rs +++ b/core/lib/external_price_api/src/forced_price_client.rs @@ -5,7 +5,7 @@ use std::{ use async_trait::async_trait; use rand::Rng; -use tokio::sync::RwLock; +use tokio::sync::Mutex; use zksync_config::configs::ExternalPriceApiClientConfig; use zksync_types::{base_token_ratio::BaseTokenAPIRatio, Address}; @@ -15,7 +15,7 @@ use crate::PriceAPIClient; #[derive(Debug)] pub struct ForcedPriceClient { ratio: BaseTokenAPIRatio, - previous_numerator: RwLock, + previous_numerator: Mutex, fluctuation: Option, next_value_fluctuation: u32, } @@ -56,7 +56,7 @@ impl ForcedPriceClient { Self { ratio, - previous_numerator: RwLock::new(NonZeroU64::new(numerator).unwrap()), + previous_numerator: Mutex::new(NonZeroU64::new(numerator).unwrap()), fluctuation, next_value_fluctuation, } @@ -68,7 +68,7 @@ impl PriceAPIClient for ForcedPriceClient { /// Returns the configured ratio with fluctuation applied if enabled async fn fetch_ratio(&self, _token_address: Address) -> anyhow::Result { if let Some(fluctation) = self.fluctuation { - let mut previous_numerator = self.previous_numerator.write().await; + let mut previous_numerator = self.previous_numerator.lock().await; let mut rng = rand::thread_rng(); let numerator_range = ( max( From 8963d0b649d80bf20b90b3efe3fb89561f719c73 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 11 Sep 2024 13:19:26 +0200 Subject: [PATCH 66/85] fix: new line --- etc/env/base/external_price_api.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/env/base/external_price_api.toml b/etc/env/base/external_price_api.toml index 803ebcae650..fe88e71e82a 100644 --- a/etc/env/base/external_price_api.toml +++ b/etc/env/base/external_price_api.toml @@ -7,4 +7,4 @@ source = "forced" [external_price_api_client.forced] numerator = 314 -denominator = 1000 \ No newline at end of file +denominator = 1000 From ca0ee753da0583dcab8c02e7d967ce55d718614d Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 11 Sep 2024 13:25:56 +0200 Subject: [PATCH 67/85] fix: rename --- core/tests/ts-integration/tests/fees.test.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 31a6aad3eda..94ccc75f8f2 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -183,7 +183,7 @@ testFees('Test fees', () => { const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 2_000_000_000n; /// set to 2 gwei - await setInternalL1GasPrice(alice._providerL2(), { + await setFeeParams(alice._providerL2(), { newL1GasPrice: l1GasPrice.toString(), newPubdataPrice: l1GasPrice.toString(), customBaseToken: !isETHBasedChain @@ -209,7 +209,7 @@ testFees('Test fees', () => { } if (!isETHBasedChain) { - await setInternalL1GasPrice(alice._providerL2(), { + await setFeeParams(alice._providerL2(), { newL1GasPrice: l1GasPrice.toString(), newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, @@ -234,7 +234,7 @@ testFees('Test fees', () => { if (isETHBasedChain) return; - await setInternalL1GasPrice(alice._providerL2(), { + await setFeeParams(alice._providerL2(), { newL1GasPrice: l1GasPrice.toString(), newPubdataPrice: l1GasPrice.toString(), customBaseToken: true, @@ -306,7 +306,7 @@ testFees('Test fees', () => { // that the gasLimit is indeed over u32::MAX, which is the most important tested property. const requiredPubdataPrice = minimalL2GasPrice * 100_000n; - await setInternalL1GasPrice(alice._providerL2(), { + await setFeeParams(alice._providerL2(), { newL1GasPrice: requiredPubdataPrice.toString(), newPubdataPrice: requiredPubdataPrice.toString() }); @@ -350,7 +350,7 @@ testFees('Test fees', () => { afterAll(async () => { // Returning the pubdata price to the default one - await setInternalL1GasPrice(alice._providerL2(), { disconnect: true }); + await setFeeParams(alice._providerL2(), { disconnect: true }); await testMaster.deinitialize(); }); @@ -364,7 +364,7 @@ async function appendResults( reports: string[] ): Promise { // For the sake of simplicity, we'll use the same pubdata price as the L1 gas prifeesce. - await setInternalL1GasPrice(sender._providerL2(), { + await setFeeParams(sender._providerL2(), { newL1GasPrice: newL1GasPrice.toString(), newPubdataPrice: newL1GasPrice.toString() }); @@ -438,7 +438,7 @@ async function killServerAndWaitForShutdown(provider: zksync.Provider) { throw new Error("Server didn't stop after a kill request"); } -async function setInternalL1GasPrice( +async function setFeeParams( provider: zksync.Provider, options: { newL1GasPrice?: string; From 38264694ea937a7cd669175d214986feeaba191e Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 11 Sep 2024 13:26:41 +0200 Subject: [PATCH 68/85] fix: spell --- core/tests/ts-integration/tests/fees.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 94ccc75f8f2..71b47a4961b 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -241,7 +241,7 @@ testFees('Test fees', () => { externalPriceApiClientForcedNumerator: 300, externalPriceApiClientForcedDenominator: 100, externalPriceApiClientForcedFluctuation: 20, - baseTokenPricePoolingIntervalMs: 1000, + baseTokenPricePollingIntervalMs: 1000, baseTokenAdjusterL1UpdateDeviationPercentage: 0 }); @@ -447,7 +447,7 @@ async function setFeeParams( externalPriceApiClientForcedNumerator?: number; externalPriceApiClientForcedDenominator?: number; externalPriceApiClientForcedFluctuation?: number; - baseTokenPricePoolingIntervalMs?: number; + baseTokenPricePollingIntervalMs?: number; baseTokenAdjusterL1UpdateDeviationPercentage?: number; disconnect?: boolean; } @@ -489,10 +489,10 @@ async function setFeeParams( command = `EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION=${options.externalPriceApiClientForcedFluctuation} ${command}`; } - if (options.baseTokenPricePoolingIntervalMs !== undefined) { - const cacheUpdateInterval = options.baseTokenPricePoolingIntervalMs / 2; + if (options.baseTokenPricePollingIntervalMs !== undefined) { + const cacheUpdateInterval = options.baseTokenPricePollingIntervalMs / 2; // To reduce price polling interval we also need to reduce base token receipt checking and tx sending sleeps as they are blocking the poller. Also cache update needs to be reduced appropriately. - command = `BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS=${options.baseTokenPricePoolingIntervalMs} BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS=${options.baseTokenPricePoolingIntervalMs} BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS=${options.baseTokenPricePoolingIntervalMs} BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS=${cacheUpdateInterval} ${command}`; + command = `BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS=${options.baseTokenPricePollingIntervalMs} BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS=${options.baseTokenPricePollingIntervalMs} BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS=${options.baseTokenPricePollingIntervalMs} BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS=${cacheUpdateInterval} ${command}`; } if (options.baseTokenAdjusterL1UpdateDeviationPercentage !== undefined) { From 8cee2b6e6182cc8ddf14dffa52f60ed0fab361f1 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 12 Sep 2024 11:41:48 +0200 Subject: [PATCH 69/85] fix: avoid hardcoding gas price in test --- core/tests/ts-integration/tests/fees.test.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 71b47a4961b..c78536fcd50 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -196,11 +196,16 @@ testFees('Test fees', () => { }) ).wait(); + const feeParams = await alice._providerL2().getFeeParams(); + const conversionRatio: { numerator: bigint; denominator: bigint } = (feeParams.V2 as any)['conversion_ratio']; + expect(conversionRatio.numerator).toBeGreaterThan(1n); + + // the minimum + compute overhead of 0.01gwei in validium mode const expectedETHGasPrice = - testMaster.environment().l1BatchCommitDataGeneratorMode === DataAvailabityMode.Rollup - ? 100_000_000 // 0.1 gwei (the minimum) - : 110_000_000; // 0.11 gwei, in validium we need to add compute overhead - const expectedCustomGasPrice = expectedETHGasPrice * 0.314; + Number(feeParams.V2.config.minimal_l2_gas_price) + + Number(feeParams.V2.config.compute_overhead_part) * 10_000_000; + const expectedCustomGasPrice = + (expectedETHGasPrice * Number(conversionRatio.numerator)) / Number(conversionRatio.denominator); if (isETHBasedChain) { expect(receipt.gasPrice).toBe(BigInt(expectedETHGasPrice)); From da45a29810bb99382d245e282145ccabca6ff833 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 12 Sep 2024 12:07:50 +0200 Subject: [PATCH 70/85] fix: cleaner application of conversion ratio. Proper check of value --- core/tests/ts-integration/tests/fees.test.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index c78536fcd50..4d7aee7bb61 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -197,21 +197,23 @@ testFees('Test fees', () => { ).wait(); const feeParams = await alice._providerL2().getFeeParams(); + // type is missing conversion_ratio field const conversionRatio: { numerator: bigint; denominator: bigint } = (feeParams.V2 as any)['conversion_ratio']; - expect(conversionRatio.numerator).toBeGreaterThan(1n); + if (isETHBasedChain) { + expect(conversionRatio.numerator).toBe(1n); + expect(conversionRatio.denominator).toBe(1n); + } else { + expect(conversionRatio.numerator).toBeGreaterThan(1n); + } // the minimum + compute overhead of 0.01gwei in validium mode const expectedETHGasPrice = Number(feeParams.V2.config.minimal_l2_gas_price) + Number(feeParams.V2.config.compute_overhead_part) * 10_000_000; - const expectedCustomGasPrice = + const expectedConvertedGasPrice = (expectedETHGasPrice * Number(conversionRatio.numerator)) / Number(conversionRatio.denominator); - if (isETHBasedChain) { - expect(receipt.gasPrice).toBe(BigInt(expectedETHGasPrice)); - } else { - expect(receipt.gasPrice).toBe(BigInt(expectedCustomGasPrice)); - } + expect(receipt.gasPrice).toBe(BigInt(expectedConvertedGasPrice)); if (!isETHBasedChain) { await setFeeParams(alice._providerL2(), { From 1f6a54d004a2ada63591bdd76d41df3b050ceb45 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Thu, 12 Sep 2024 13:49:02 +0200 Subject: [PATCH 71/85] fix: update overhead calculation logic, some bigint improvements --- core/tests/ts-integration/tests/fees.test.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 4d7aee7bb61..fffda929edf 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -197,21 +197,23 @@ testFees('Test fees', () => { ).wait(); const feeParams = await alice._providerL2().getFeeParams(); + const feeConfig = feeParams.V2.config; // type is missing conversion_ratio field const conversionRatio: { numerator: bigint; denominator: bigint } = (feeParams.V2 as any)['conversion_ratio']; if (isETHBasedChain) { - expect(conversionRatio.numerator).toBe(1n); - expect(conversionRatio.denominator).toBe(1n); + expect(conversionRatio.numerator).toBe(1); //number not bigint for some reason + expect(conversionRatio.denominator).toBe(1); } else { expect(conversionRatio.numerator).toBeGreaterThan(1n); } // the minimum + compute overhead of 0.01gwei in validium mode const expectedETHGasPrice = - Number(feeParams.V2.config.minimal_l2_gas_price) + - Number(feeParams.V2.config.compute_overhead_part) * 10_000_000; + feeConfig.minimal_l2_gas_price + + (feeConfig.compute_overhead_part * feeParams.V2.l1_gas_price * feeConfig.batch_overhead_l1_gas) / + feeConfig.max_gas_per_batch; const expectedConvertedGasPrice = - (expectedETHGasPrice * Number(conversionRatio.numerator)) / Number(conversionRatio.denominator); + (expectedETHGasPrice * conversionRatio.numerator) / conversionRatio.denominator; expect(receipt.gasPrice).toBe(BigInt(expectedConvertedGasPrice)); @@ -231,7 +233,7 @@ testFees('Test fees', () => { }) ).wait(); - const expectedCustomGasPrice = expectedETHGasPrice * 2.71; + const expectedCustomGasPrice = (BigInt(expectedETHGasPrice) * 271n) / 100n; expect(receipt2.gasPrice).toBe(BigInt(expectedCustomGasPrice)); } }); From 45e720a3fa7ac010e68bf11ce050c2566370c63b Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 13 Sep 2024 19:02:55 +0200 Subject: [PATCH 72/85] fix: remove less useful test --- core/tests/ts-integration/tests/fees.test.ts | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index fffda929edf..528d0d9575d 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -216,26 +216,6 @@ testFees('Test fees', () => { (expectedETHGasPrice * conversionRatio.numerator) / conversionRatio.denominator; expect(receipt.gasPrice).toBe(BigInt(expectedConvertedGasPrice)); - - if (!isETHBasedChain) { - await setFeeParams(alice._providerL2(), { - newL1GasPrice: l1GasPrice.toString(), - newPubdataPrice: l1GasPrice.toString(), - customBaseToken: true, - externalPriceApiClientForcedNumerator: 271, - externalPriceApiClientForcedDenominator: 100 - }); - - const receipt2 = await ( - await alice.sendTransaction({ - to: receiver, - value: BigInt(1) - }) - ).wait(); - - const expectedCustomGasPrice = (BigInt(expectedETHGasPrice) * 271n) / 100n; - expect(receipt2.gasPrice).toBe(BigInt(expectedCustomGasPrice)); - } }); test('Test base token ratio fluctuations', async () => { From b3a24726a3a0c8d8adb8b9b554af65a9d08cdb9d Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 23 Sep 2024 13:23:44 +0200 Subject: [PATCH 73/85] fix: remove empty file --- .github/workflows/ci-zk-toolbox-reusable.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/workflows/ci-zk-toolbox-reusable.yml diff --git a/.github/workflows/ci-zk-toolbox-reusable.yml b/.github/workflows/ci-zk-toolbox-reusable.yml deleted file mode 100644 index e69de29bb2d..00000000000 From 6654d28528f4cd26edeb2b21b07337fd76665047 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 23 Sep 2024 13:26:08 +0200 Subject: [PATCH 74/85] fix: proper base token values in toolbox run tests --- .github/workflows/ci-core-reusable.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-core-reusable.yml b/.github/workflows/ci-core-reusable.yml index 53ff6439829..9653ab6392e 100644 --- a/.github/workflows/ci-core-reusable.yml +++ b/.github/workflows/ci-core-reusable.yml @@ -257,8 +257,8 @@ jobs: --wallet-creation localhost \ --l1-batch-commit-data-generator-mode rollup \ --base-token-address ${{ env.address }} \ - --base-token-price-nominator 3 \ - --base-token-price-denominator 2 \ + --base-token-price-nominator 314 \ + --base-token-price-denominator 1000 \ --set-as-default false \ --ignore-prerequisites @@ -316,8 +316,8 @@ jobs: --wallet-creation localhost \ --l1-batch-commit-data-generator-mode validium \ --base-token-address ${{ env.address }} \ - --base-token-price-nominator 3 \ - --base-token-price-denominator 2 \ + --base-token-price-nominator 314 \ + --base-token-price-denominator 1000 \ --set-as-default false \ --ignore-prerequisites From f11a099a63c70a4944cedf7a346dfaa64036ee5f Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 1 Oct 2024 18:34:38 +0200 Subject: [PATCH 75/85] feat: migrated to new way of starting server in fees test also refactored a little how server is configured for fees test --- core/tests/ts-integration/src/utils.ts | 164 +++++++++++++++---- core/tests/ts-integration/tests/fees.test.ts | 38 ++--- core/tests/ts-integration/tests/utils.ts | 81 --------- 3 files changed, 150 insertions(+), 133 deletions(-) delete mode 100644 core/tests/ts-integration/tests/utils.ts diff --git a/core/tests/ts-integration/src/utils.ts b/core/tests/ts-integration/src/utils.ts index 128d0be57d0..ccbdc3b6b0f 100644 --- a/core/tests/ts-integration/src/utils.ts +++ b/core/tests/ts-integration/src/utils.ts @@ -1,17 +1,12 @@ import { spawn as _spawn, ChildProcessWithoutNullStreams, type ProcessEnvOptions } from 'child_process'; import { assert } from 'chai'; -import { FileConfig } from 'utils/build/file-configs'; +import {FileConfig, getConfigPath} from 'utils/build/file-configs'; import { killPidWithAllChilds } from 'utils/build/kill'; import * as utils from 'utils'; import fs from 'node:fs/promises'; import * as zksync from 'zksync-ethers'; -import { - deleteInternalEnforcedL1GasPrice, - deleteInternalEnforcedPubdataPrice, - setInternalEnforcedL1GasPrice, - setInternalEnforcedPubdataPrice, - setTransactionSlots -} from '../tests/utils'; +import * as fsSync from 'fs'; + // executes a command in background and returns a child process handle // by default pipes data to parent's stdio but this can be overridden @@ -106,47 +101,120 @@ export class Node { } export class NodeSpawner { + private readonly generalConfigPath: string | undefined; + private readonly originalConfig: string | undefined; + public constructor( private readonly pathToHome: string, private readonly logs: fs.FileHandle, private readonly fileConfig: FileConfig, private readonly options: MainNodeSpawnOptions, private env?: ProcessEnvOptions['env'] - ) {} + ) { + if (fileConfig.loadFromFile) { + const generalConfigPath = getConfigPath({ + pathToHome, + chain: fileConfig.chain, + configsFolder: 'configs', + config: 'general.yaml' + }); + this.originalConfig = fsSync.readFileSync(generalConfigPath, 'utf8'); + } + } - public async spawnMainNode(newL1GasPrice?: string, newPubdataPrice?: string): Promise> { + public async spawnMainNode(overrides: { + newL1GasPrice?: bigint; + newPubdataPrice?: bigint; + customBaseToken?: boolean; + externalPriceApiClientForcedNumerator?: number; + externalPriceApiClientForcedDenominator?: number; + externalPriceApiClientForcedFluctuation?: number; + baseTokenPricePollingIntervalMs?: number; + baseTokenAdjusterL1UpdateDeviationPercentage?: number; + } | null = null + ): Promise> { const env = this.env ?? process.env; const { fileConfig, pathToHome, options, logs } = this; - const testMode = newPubdataPrice || newL1GasPrice; + const testMode = overrides?.newPubdataPrice != null || overrides?.newL1GasPrice != null; - console.log('New L1 Gas Price: ', newL1GasPrice); - console.log('New Pubdata Price: ', newPubdataPrice); + console.log('Overrides: ', overrides); if (fileConfig.loadFromFile) { - setTransactionSlots(pathToHome, fileConfig, testMode ? 1 : 8192); + this.restoreConfig(); + this.setPropertyInGeneralConfig('transaction_slots', testMode ? 1 : 8192); - if (newL1GasPrice) { - setInternalEnforcedL1GasPrice(pathToHome, fileConfig, parseFloat(newL1GasPrice)); - } else { - deleteInternalEnforcedL1GasPrice(pathToHome, fileConfig); - } + if (overrides != null) { + if (overrides.newL1GasPrice) { + this.setChildProperty('gas_adjuster','internal_enforced_l1_gas_price', overrides.newL1GasPrice); + } + + if (overrides.newPubdataPrice) { + this.setChildProperty('gas_adjuster','internal_enforced_pubdata_price', overrides.newPubdataPrice); + } + + if (overrides.externalPriceApiClientForcedNumerator !== undefined) { + this.setChildProperty('external_price_api_client','forced_numerator', overrides.externalPriceApiClientForcedNumerator); + } - if (newPubdataPrice) { - setInternalEnforcedPubdataPrice(pathToHome, fileConfig, parseFloat(newPubdataPrice)); - } else { - deleteInternalEnforcedPubdataPrice(pathToHome, fileConfig); + if (overrides.externalPriceApiClientForcedDenominator !== undefined) { + this.setChildProperty('external_price_api_client', 'forced_denominator', overrides.externalPriceApiClientForcedDenominator); + } + + if (overrides.externalPriceApiClientForcedFluctuation !== undefined) { + this.setChildProperty('external_price_api_client', 'forced_fluctuation', overrides.externalPriceApiClientForcedFluctuation); + } + + if (overrides.baseTokenPricePollingIntervalMs !== undefined) { + const cacheUpdateInterval = overrides.baseTokenPricePollingIntervalMs / 2; + // To reduce price polling interval we also need to reduce base token receipt checking and tx sending sleeps as they are blocking the poller. Also cache update needs to be reduced appropriately. + this.setChildProperty('base_token_adjuster', 'l1_receipt_checking_sleep_ms', overrides.baseTokenPricePollingIntervalMs); + this.setChildProperty('base_token_adjuster', 'l1_tx_sending_sleep_ms', overrides.baseTokenPricePollingIntervalMs); + this.setChildProperty('base_token_adjuster', 'price_polling_interval_ms', overrides.baseTokenPricePollingIntervalMs); + this.setChildProperty('base_token_adjuster', 'price_cache_update_interval_ms' , cacheUpdateInterval); + } + + if (overrides.baseTokenAdjusterL1UpdateDeviationPercentage !== undefined) { + this.setChildProperty('base_token_adjuster', 'l1_update_deviation_percentage', overrides.baseTokenAdjusterL1UpdateDeviationPercentage); + } } } else { env['DATABASE_MERKLE_TREE_MODE'] = 'full'; - if (newPubdataPrice) { - env['ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_PUBDATA_PRICE'] = newPubdataPrice; - } + if (overrides != null) { + if (overrides.newPubdataPrice) { + env['ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_PUBDATA_PRICE'] = overrides.newPubdataPrice.toString(); + } - if (newL1GasPrice) { - // We need to ensure that each transaction gets into its own batch for more fair comparison. - env['ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_L1_GAS_PRICE'] = newL1GasPrice; + if (overrides.newL1GasPrice) { + // We need to ensure that each transaction gets into its own batch for more fair comparison. + env['ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_L1_GAS_PRICE'] = overrides.newL1GasPrice.toString(); + } + + if (overrides.externalPriceApiClientForcedNumerator !== undefined) { + env['EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR'] = overrides.externalPriceApiClientForcedNumerator.toString(); + } + + if (overrides.externalPriceApiClientForcedDenominator !== undefined) { + env['EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR'] = overrides.externalPriceApiClientForcedDenominator.toString(); + } + + if (overrides.externalPriceApiClientForcedFluctuation !== undefined) { + env['EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION'] = overrides.externalPriceApiClientForcedFluctuation.toString(); + } + + if (overrides.baseTokenPricePollingIntervalMs !== undefined) { + const cacheUpdateInterval = overrides.baseTokenPricePollingIntervalMs / 2; + // To reduce price polling interval we also need to reduce base token receipt checking and tx sending sleeps as they are blocking the poller. Also cache update needs to be reduced appropriately. + env['BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS'] = overrides.baseTokenPricePollingIntervalMs.toString(); + env['BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS'] = overrides.baseTokenPricePollingIntervalMs.toString(); + env['BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS'] = overrides.baseTokenPricePollingIntervalMs.toString(); + env['BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS'] = cacheUpdateInterval.toString(); + } + + if (overrides.baseTokenAdjusterL1UpdateDeviationPercentage !== undefined) { + env['BASE_TOKEN_ADJUSTER_L1_UPDATE_DEVIATION_PERCENTAGE'] = overrides.baseTokenAdjusterL1UpdateDeviationPercentage.toString(); + } } if (testMode) { @@ -175,6 +243,44 @@ export class NodeSpawner { await waitForNodeToStart(proc, options.apiWeb3JsonRpcHttpUrl); return new Node(proc, options.apiWeb3JsonRpcHttpUrl, NodeType.MAIN); } + + public restoreConfig() { + if (this.generalConfigPath != void 0 && this.originalConfig != void 0) + fsSync.writeFileSync(this.generalConfigPath, this.originalConfig, 'utf8'); + } + + private setChildProperty(parentProperty: string, property: string, value: number | bigint) { + if (this.generalConfigPath == void 0) + throw new Error("Trying to set property in config while not in file mode"); + const generalConfig = fsSync.readFileSync(this.generalConfigPath, 'utf8'); + + // Define the regex pattern to check if the property already exists + const propertyRegex = new RegExp(`(^\\s*${property}:\\s*\\d+(\\.\\d+)?$)`, 'm'); + const gasAdjusterRegex = new RegExp(`(^\\s*${parentProperty}:.*$)`, 'gm'); + + let newGeneralConfig; + + if (propertyRegex.test(generalConfig)) { + // If the property exists, modify its value + newGeneralConfig = generalConfig.replace(propertyRegex, ` ${property}: ${value}`); + } else { + // If the property does not exist, add it under the gas_adjuster section + newGeneralConfig = generalConfig.replace(gasAdjusterRegex, `$1\n ${property}: ${value}`); + } + + fsSync.writeFileSync(this.generalConfigPath, newGeneralConfig, 'utf8'); + } + + private setPropertyInGeneralConfig(property: string, value: number) { + if (this.generalConfigPath == void 0) + throw new Error("Trying to set property in config while not in file mode"); + const generalConfig = fsSync.readFileSync(this.generalConfigPath, 'utf8'); + + const regex = new RegExp(`${property}:\\s*\\d+(\\.\\d+)?`, 'g'); + const newGeneralConfig = generalConfig.replace(regex, `${property}: ${value}`); + + fsSync.writeFileSync(this.generalConfigPath, newGeneralConfig, 'utf8'); + } } async function waitForNodeToStart(proc: ChildProcessWithoutNullStreams, l2Url: string) { diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 29037ec2bfd..b72d894fba9 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -17,11 +17,9 @@ import * as ethers from 'ethers'; import { DataAvailabityMode, Token } from '../src/types'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; import { loadConfig, shouldLoadConfigFromFile } from 'utils/build/file-configs'; -import { logsTestPath } from 'utils/build/logs'; +import { logsTestPath, killPidWithAllChilds } from 'utils/build/logs'; import path from 'path'; import { NodeSpawner, Node, NodeType } from '../src/utils'; -import { deleteInternalEnforcedL1GasPrice, deleteInternalEnforcedPubdataPrice, setTransactionSlots } from './utils'; -import { killPidWithAllChilds } from 'utils/build/kill'; import { sendTransfers } from '../src/context-owner'; import { Reporter } from '../src/reporter'; @@ -136,9 +134,6 @@ testFees('Test fees', function () { alice._providerL1() ); - const bridgehub = await mainWallet.getBridgehubContract(); - const chainId = testMaster.environment().l2ChainId; - const baseTokenAddress = await bridgehub.baseToken(chainId); isETHBasedChain = baseTokenAddress == zksync.utils.ETH_ADDRESS_IN_CONTRACTS; // On non ETH based chains the standard deposit is not enough to run all this tests @@ -214,7 +209,10 @@ testFees('Test fees', function () { for (const gasPrice of L1_GAS_PRICES_TO_TEST) { // For the sake of simplicity, we'll use the same pubdata price as the L1 gas price. await mainNode.killAndWaitForShutdown(); - mainNode = await mainNodeSpawner.spawnMainNode(gasPrice.toString(), gasPrice.toString()); + mainNode = await mainNodeSpawner.spawnMainNode({ + newL1GasPrice: gasPrice, + newPubdataPrice: gasPrice + }); reports = await appendResults( alice, @@ -253,10 +251,9 @@ testFees('Test fees', function () { const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 2_000_000_000n; /// set to 2 gwei - await setFeeParams(alice._providerL2(), { - newL1GasPrice: l1GasPrice.toString(), - newPubdataPrice: l1GasPrice.toString(), - customBaseToken: !isETHBasedChain + await mainNodeSpawner.spawnMainNode({ + newL1GasPrice: l1GasPrice, + newPubdataPrice: l1GasPrice, }); const receipt = await ( @@ -293,10 +290,9 @@ testFees('Test fees', function () { if (isETHBasedChain) return; - await setFeeParams(alice._providerL2(), { - newL1GasPrice: l1GasPrice.toString(), - newPubdataPrice: l1GasPrice.toString(), - customBaseToken: true, + await mainNodeSpawner.spawnMainNode({ + newL1GasPrice: l1GasPrice, + newPubdataPrice: l1GasPrice, externalPriceApiClientForcedNumerator: 300, externalPriceApiClientForcedDenominator: 100, externalPriceApiClientForcedFluctuation: 20, @@ -366,9 +362,9 @@ testFees('Test fees', function () { const requiredPubdataPrice = minimalL2GasPrice * 100_000n; await mainNode.killAndWaitForShutdown(); - mainNode = await mainNodeSpawner.spawnMainNode( - requiredPubdataPrice.toString(), - requiredPubdataPrice.toString() + mainNode = await mainNodeSpawner.spawnMainNode({ + newL1GasPrice: requiredPubdataPrice, + newPubdataPrice: requiredPubdataPrice} ); const l1Messenger = new ethers.Contract(zksync.utils.L1_MESSENGER_ADDRESS, zksync.utils.L1_MESSENGER, alice); @@ -413,11 +409,7 @@ testFees('Test fees', function () { await testMaster.deinitialize(); await mainNode.killAndWaitForShutdown(); // Returning the pubdata price to the default one - - // Restore defaults - setTransactionSlots(pathToHome, fileConfig, 8192); - deleteInternalEnforcedL1GasPrice(pathToHome, fileConfig); - deleteInternalEnforcedPubdataPrice(pathToHome, fileConfig); + // Spawning with no options restores defaults. mainNode = await mainNodeSpawner.spawnMainNode(); __ZKSYNC_TEST_CONTEXT_OWNER__.setL2NodePid(mainNode.proc.pid!); }); diff --git a/core/tests/ts-integration/tests/utils.ts b/core/tests/ts-integration/tests/utils.ts deleted file mode 100644 index 24df8a170c2..00000000000 --- a/core/tests/ts-integration/tests/utils.ts +++ /dev/null @@ -1,81 +0,0 @@ -import * as fs from 'fs'; -import { getConfigPath } from 'utils/build/file-configs'; - -export function setInternalEnforcedPubdataPrice(pathToHome: string, fileConfig: any, value: number) { - setGasAdjusterProperty(pathToHome, fileConfig, 'internal_enforced_pubdata_price', value); -} - -export function setInternalEnforcedL1GasPrice(pathToHome: string, fileConfig: any, value: number) { - setGasAdjusterProperty(pathToHome, fileConfig, 'internal_enforced_l1_gas_price', value); -} - -export function deleteInternalEnforcedPubdataPrice(pathToHome: string, fileConfig: any) { - deleteProperty(pathToHome, fileConfig, 'internal_enforced_pubdata_price'); -} - -export function deleteInternalEnforcedL1GasPrice(pathToHome: string, fileConfig: any) { - deleteProperty(pathToHome, fileConfig, 'internal_enforced_l1_gas_price'); -} - -export function setTransactionSlots(pathToHome: string, fileConfig: any, value: number) { - setPropertyInGeneralConfig(pathToHome, fileConfig, 'transaction_slots', value); -} - -function setPropertyInGeneralConfig(pathToHome: string, fileConfig: any, property: string, value: number) { - const generalConfigPath = getConfigPath({ - pathToHome, - chain: fileConfig.chain, - configsFolder: 'configs', - config: 'general.yaml' - }); - const generalConfig = fs.readFileSync(generalConfigPath, 'utf8'); - - const regex = new RegExp(`${property}:\\s*\\d+(\\.\\d+)?`, 'g'); - const newGeneralConfig = generalConfig.replace(regex, `${property}: ${value}`); - - fs.writeFileSync(generalConfigPath, newGeneralConfig, 'utf8'); -} - -function setGasAdjusterProperty(pathToHome: string, fileConfig: any, property: string, value: number) { - const generalConfigPath = getConfigPath({ - pathToHome, - chain: fileConfig.chain, - configsFolder: 'configs', - config: 'general.yaml' - }); - const generalConfig = fs.readFileSync(generalConfigPath, 'utf8'); - - // Define the regex pattern to check if the property already exists - const propertyRegex = new RegExp(`(^\\s*${property}:\\s*\\d+(\\.\\d+)?$)`, 'm'); - const gasAdjusterRegex = new RegExp('(^\\s*gas_adjuster:.*$)', 'gm'); - - let newGeneralConfig; - - if (propertyRegex.test(generalConfig)) { - // If the property exists, modify its value - newGeneralConfig = generalConfig.replace(propertyRegex, ` ${property}: ${value}`); - } else { - // If the property does not exist, add it under the gas_adjuster section - newGeneralConfig = generalConfig.replace(gasAdjusterRegex, `$1\n ${property}: ${value}`); - } - - fs.writeFileSync(generalConfigPath, newGeneralConfig, 'utf8'); -} - -function deleteProperty(pathToHome: string, fileConfig: any, property: string) { - const generalConfigPath = getConfigPath({ - pathToHome, - chain: fileConfig.chain, - configsFolder: 'configs', - config: 'general.yaml' - }); - const generalConfig = fs.readFileSync(generalConfigPath, 'utf8'); - - // Define the regex pattern to find the property line and remove it completely - const propertyRegex = new RegExp(`^\\s*${property}:.*\\n?`, 'm'); - - // Remove the line if the property exists - const newGeneralConfig = generalConfig.replace(propertyRegex, ''); - - fs.writeFileSync(generalConfigPath, newGeneralConfig, 'utf8'); -} From 70fae209497573854df316ba2858632b7baf52b3 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 2 Oct 2024 19:32:38 +0200 Subject: [PATCH 76/85] fix: import issues, missing kill, format --- core/tests/ts-integration/src/utils.ts | 86 ++++++++++++++------ core/tests/ts-integration/tests/fees.test.ts | 16 ++-- 2 files changed, 71 insertions(+), 31 deletions(-) diff --git a/core/tests/ts-integration/src/utils.ts b/core/tests/ts-integration/src/utils.ts index ccbdc3b6b0f..3acf080a504 100644 --- a/core/tests/ts-integration/src/utils.ts +++ b/core/tests/ts-integration/src/utils.ts @@ -1,13 +1,12 @@ import { spawn as _spawn, ChildProcessWithoutNullStreams, type ProcessEnvOptions } from 'child_process'; import { assert } from 'chai'; -import {FileConfig, getConfigPath} from 'utils/build/file-configs'; +import { FileConfig, getConfigPath } from 'utils/build/file-configs'; import { killPidWithAllChilds } from 'utils/build/kill'; import * as utils from 'utils'; import fs from 'node:fs/promises'; import * as zksync from 'zksync-ethers'; import * as fsSync from 'fs'; - // executes a command in background and returns a child process handle // by default pipes data to parent's stdio but this can be overridden export function runServerInBackground({ @@ -112,17 +111,18 @@ export class NodeSpawner { private env?: ProcessEnvOptions['env'] ) { if (fileConfig.loadFromFile) { - const generalConfigPath = getConfigPath({ + this.generalConfigPath = getConfigPath({ pathToHome, chain: fileConfig.chain, configsFolder: 'configs', config: 'general.yaml' }); - this.originalConfig = fsSync.readFileSync(generalConfigPath, 'utf8'); + this.originalConfig = fsSync.readFileSync(this.generalConfigPath, 'utf8'); } } - public async spawnMainNode(overrides: { + public async spawnMainNode( + overrides: { newL1GasPrice?: bigint; newPubdataPrice?: bigint; customBaseToken?: boolean; @@ -146,36 +146,64 @@ export class NodeSpawner { if (overrides != null) { if (overrides.newL1GasPrice) { - this.setChildProperty('gas_adjuster','internal_enforced_l1_gas_price', overrides.newL1GasPrice); + this.setChildProperty('gas_adjuster', 'internal_enforced_l1_gas_price', overrides.newL1GasPrice); } if (overrides.newPubdataPrice) { - this.setChildProperty('gas_adjuster','internal_enforced_pubdata_price', overrides.newPubdataPrice); + this.setChildProperty('gas_adjuster', 'internal_enforced_pubdata_price', overrides.newPubdataPrice); } if (overrides.externalPriceApiClientForcedNumerator !== undefined) { - this.setChildProperty('external_price_api_client','forced_numerator', overrides.externalPriceApiClientForcedNumerator); + this.setChildProperty( + 'external_price_api_client', + 'forced_numerator', + overrides.externalPriceApiClientForcedNumerator + ); } if (overrides.externalPriceApiClientForcedDenominator !== undefined) { - this.setChildProperty('external_price_api_client', 'forced_denominator', overrides.externalPriceApiClientForcedDenominator); + this.setChildProperty( + 'external_price_api_client', + 'forced_denominator', + overrides.externalPriceApiClientForcedDenominator + ); } if (overrides.externalPriceApiClientForcedFluctuation !== undefined) { - this.setChildProperty('external_price_api_client', 'forced_fluctuation', overrides.externalPriceApiClientForcedFluctuation); + this.setChildProperty( + 'external_price_api_client', + 'forced_fluctuation', + overrides.externalPriceApiClientForcedFluctuation + ); } if (overrides.baseTokenPricePollingIntervalMs !== undefined) { const cacheUpdateInterval = overrides.baseTokenPricePollingIntervalMs / 2; // To reduce price polling interval we also need to reduce base token receipt checking and tx sending sleeps as they are blocking the poller. Also cache update needs to be reduced appropriately. - this.setChildProperty('base_token_adjuster', 'l1_receipt_checking_sleep_ms', overrides.baseTokenPricePollingIntervalMs); - this.setChildProperty('base_token_adjuster', 'l1_tx_sending_sleep_ms', overrides.baseTokenPricePollingIntervalMs); - this.setChildProperty('base_token_adjuster', 'price_polling_interval_ms', overrides.baseTokenPricePollingIntervalMs); - this.setChildProperty('base_token_adjuster', 'price_cache_update_interval_ms' , cacheUpdateInterval); + this.setChildProperty( + 'base_token_adjuster', + 'l1_receipt_checking_sleep_ms', + overrides.baseTokenPricePollingIntervalMs + ); + this.setChildProperty( + 'base_token_adjuster', + 'l1_tx_sending_sleep_ms', + overrides.baseTokenPricePollingIntervalMs + ); + this.setChildProperty( + 'base_token_adjuster', + 'price_polling_interval_ms', + overrides.baseTokenPricePollingIntervalMs + ); + this.setChildProperty('base_token_adjuster', 'price_cache_update_interval_ms', cacheUpdateInterval); } if (overrides.baseTokenAdjusterL1UpdateDeviationPercentage !== undefined) { - this.setChildProperty('base_token_adjuster', 'l1_update_deviation_percentage', overrides.baseTokenAdjusterL1UpdateDeviationPercentage); + this.setChildProperty( + 'base_token_adjuster', + 'l1_update_deviation_percentage', + overrides.baseTokenAdjusterL1UpdateDeviationPercentage + ); } } } else { @@ -183,7 +211,8 @@ export class NodeSpawner { if (overrides != null) { if (overrides.newPubdataPrice) { - env['ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_PUBDATA_PRICE'] = overrides.newPubdataPrice.toString(); + env['ETH_SENDER_GAS_ADJUSTER_INTERNAL_ENFORCED_PUBDATA_PRICE'] = + overrides.newPubdataPrice.toString(); } if (overrides.newL1GasPrice) { @@ -192,28 +221,35 @@ export class NodeSpawner { } if (overrides.externalPriceApiClientForcedNumerator !== undefined) { - env['EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR'] = overrides.externalPriceApiClientForcedNumerator.toString(); + env['EXTERNAL_PRICE_API_CLIENT_FORCED_NUMERATOR'] = + overrides.externalPriceApiClientForcedNumerator.toString(); } if (overrides.externalPriceApiClientForcedDenominator !== undefined) { - env['EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR'] = overrides.externalPriceApiClientForcedDenominator.toString(); + env['EXTERNAL_PRICE_API_CLIENT_FORCED_DENOMINATOR'] = + overrides.externalPriceApiClientForcedDenominator.toString(); } if (overrides.externalPriceApiClientForcedFluctuation !== undefined) { - env['EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION'] = overrides.externalPriceApiClientForcedFluctuation.toString(); + env['EXTERNAL_PRICE_API_CLIENT_FORCED_FLUCTUATION'] = + overrides.externalPriceApiClientForcedFluctuation.toString(); } if (overrides.baseTokenPricePollingIntervalMs !== undefined) { const cacheUpdateInterval = overrides.baseTokenPricePollingIntervalMs / 2; // To reduce price polling interval we also need to reduce base token receipt checking and tx sending sleeps as they are blocking the poller. Also cache update needs to be reduced appropriately. - env['BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS'] = overrides.baseTokenPricePollingIntervalMs.toString(); - env['BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS'] = overrides.baseTokenPricePollingIntervalMs.toString(); - env['BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS'] = overrides.baseTokenPricePollingIntervalMs.toString(); + env['BASE_TOKEN_ADJUSTER_L1_RECEIPT_CHECKING_SLEEP_MS'] = + overrides.baseTokenPricePollingIntervalMs.toString(); + env['BASE_TOKEN_ADJUSTER_L1_TX_SENDING_SLEEP_MS'] = + overrides.baseTokenPricePollingIntervalMs.toString(); + env['BASE_TOKEN_ADJUSTER_PRICE_POLLING_INTERVAL_MS'] = + overrides.baseTokenPricePollingIntervalMs.toString(); env['BASE_TOKEN_ADJUSTER_PRICE_CACHE_UPDATE_INTERVAL_MS'] = cacheUpdateInterval.toString(); } if (overrides.baseTokenAdjusterL1UpdateDeviationPercentage !== undefined) { - env['BASE_TOKEN_ADJUSTER_L1_UPDATE_DEVIATION_PERCENTAGE'] = overrides.baseTokenAdjusterL1UpdateDeviationPercentage.toString(); + env['BASE_TOKEN_ADJUSTER_L1_UPDATE_DEVIATION_PERCENTAGE'] = + overrides.baseTokenAdjusterL1UpdateDeviationPercentage.toString(); } } @@ -251,7 +287,7 @@ export class NodeSpawner { private setChildProperty(parentProperty: string, property: string, value: number | bigint) { if (this.generalConfigPath == void 0) - throw new Error("Trying to set property in config while not in file mode"); + throw new Error('Trying to set property in config while not in file mode'); const generalConfig = fsSync.readFileSync(this.generalConfigPath, 'utf8'); // Define the regex pattern to check if the property already exists @@ -273,7 +309,7 @@ export class NodeSpawner { private setPropertyInGeneralConfig(property: string, value: number) { if (this.generalConfigPath == void 0) - throw new Error("Trying to set property in config while not in file mode"); + throw new Error('Trying to set property in config while not in file mode'); const generalConfig = fsSync.readFileSync(this.generalConfigPath, 'utf8'); const regex = new RegExp(`${property}:\\s*\\d+(\\.\\d+)?`, 'g'); diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index b72d894fba9..15826dda0da 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -17,7 +17,9 @@ import * as ethers from 'ethers'; import { DataAvailabityMode, Token } from '../src/types'; import { SYSTEM_CONTEXT_ADDRESS, getTestContract } from '../src/helpers'; import { loadConfig, shouldLoadConfigFromFile } from 'utils/build/file-configs'; -import { logsTestPath, killPidWithAllChilds } from 'utils/build/logs'; +import { logsTestPath } from 'utils/build/logs'; +import { sleep } from 'utils/build'; +import { killPidWithAllChilds } from 'utils/build/kill'; import path from 'path'; import { NodeSpawner, Node, NodeType } from '../src/utils'; import { sendTransfers } from '../src/context-owner'; @@ -251,9 +253,10 @@ testFees('Test fees', function () { const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 2_000_000_000n; /// set to 2 gwei + await mainNode.killAndWaitForShutdown(); await mainNodeSpawner.spawnMainNode({ newL1GasPrice: l1GasPrice, - newPubdataPrice: l1GasPrice, + newPubdataPrice: l1GasPrice }); const receipt = await ( @@ -290,6 +293,7 @@ testFees('Test fees', function () { if (isETHBasedChain) return; + await mainNode.killAndWaitForShutdown(); await mainNodeSpawner.spawnMainNode({ newL1GasPrice: l1GasPrice, newPubdataPrice: l1GasPrice, @@ -306,7 +310,7 @@ testFees('Test fees', function () { let changedL2 = false; let changedL1 = false; for (let i = 0; i < 20; i++) { - await utils.sleep(0.5); + await sleep(0.5); const newFeeParams = await alice._providerL2().getFeeParams(); // we need any as FeeParams is missing existing conversion_ratio field @@ -335,7 +339,7 @@ testFees('Test fees', function () { changedL1 = true; break; } - await utils.sleep(0.5); + await sleep(0.5); } expect(changedL1).toBeTruthy(); @@ -364,8 +368,8 @@ testFees('Test fees', function () { await mainNode.killAndWaitForShutdown(); mainNode = await mainNodeSpawner.spawnMainNode({ newL1GasPrice: requiredPubdataPrice, - newPubdataPrice: requiredPubdataPrice} - ); + newPubdataPrice: requiredPubdataPrice + }); const l1Messenger = new ethers.Contract(zksync.utils.L1_MESSENGER_ADDRESS, zksync.utils.L1_MESSENGER, alice); From 64c7240e0ee080035a1d068399d9e19be84558fd Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 9 Oct 2024 11:07:47 +0200 Subject: [PATCH 77/85] debug: debug logs --- core/tests/ts-integration/tests/fees.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 15826dda0da..91db1945897 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -285,6 +285,10 @@ testFees('Test fees', function () { const expectedConvertedGasPrice = (expectedETHGasPrice * conversionRatio.numerator) / conversionRatio.denominator; + console.log('feeParams', feeParams); + console.log('receipt', receipt); + console.log('gas price', await alice._providerL2().getGasPrice()); + console.log(await alice._providerL2().getFeeParams()); expect(receipt.gasPrice).toBe(BigInt(expectedConvertedGasPrice)); }); From 1c6de49864463a4e146f0ce5c2ed6332f4abb2a1 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 9 Oct 2024 14:15:29 +0200 Subject: [PATCH 78/85] fix: node spawning bug --- core/tests/ts-integration/tests/fees.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 91db1945897..dc33a54e750 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -254,7 +254,7 @@ testFees('Test fees', function () { const l1GasPrice = 2_000_000_000n; /// set to 2 gwei await mainNode.killAndWaitForShutdown(); - await mainNodeSpawner.spawnMainNode({ + mainNode = await mainNodeSpawner.spawnMainNode({ newL1GasPrice: l1GasPrice, newPubdataPrice: l1GasPrice }); @@ -298,7 +298,7 @@ testFees('Test fees', function () { if (isETHBasedChain) return; await mainNode.killAndWaitForShutdown(); - await mainNodeSpawner.spawnMainNode({ + mainNode = await mainNodeSpawner.spawnMainNode({ newL1GasPrice: l1GasPrice, newPubdataPrice: l1GasPrice, externalPriceApiClientForcedNumerator: 300, From b03433b522958bfc653a380c6d3b06cd13de0b04 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Fri, 11 Oct 2024 19:13:28 +0200 Subject: [PATCH 79/85] feat: simplify node spawning to avoid forgotten nodes --- core/tests/ts-integration/src/env.ts | 3 +- core/tests/ts-integration/src/utils.ts | 33 +++++++++++++------- core/tests/ts-integration/tests/fees.test.ts | 24 ++++++-------- 3 files changed, 32 insertions(+), 28 deletions(-) diff --git a/core/tests/ts-integration/src/env.ts b/core/tests/ts-integration/src/env.ts index 1de917c2362..596872ab9c5 100644 --- a/core/tests/ts-integration/src/env.ts +++ b/core/tests/ts-integration/src/env.ts @@ -117,7 +117,8 @@ async function loadTestEnvironmentFromFile(fileConfig: FileConfig): Promise { } } +interface MainNodeOptions { + newL1GasPrice?: bigint; + newPubdataPrice?: bigint; + customBaseToken?: boolean; + externalPriceApiClientForcedNumerator?: number; + externalPriceApiClientForcedDenominator?: number; + externalPriceApiClientForcedFluctuation?: number; + baseTokenPricePollingIntervalMs?: number; + baseTokenAdjusterL1UpdateDeviationPercentage?: number; +} export class NodeSpawner { private readonly generalConfigPath: string | undefined; private readonly originalConfig: string | undefined; + public mainNode: Node | null; public constructor( private readonly pathToHome: string, @@ -110,6 +121,7 @@ export class NodeSpawner { private readonly options: MainNodeSpawnOptions, private env?: ProcessEnvOptions['env'] ) { + this.mainNode = null; if (fileConfig.loadFromFile) { this.generalConfigPath = getConfigPath({ pathToHome, @@ -121,18 +133,15 @@ export class NodeSpawner { } } - public async spawnMainNode( - overrides: { - newL1GasPrice?: bigint; - newPubdataPrice?: bigint; - customBaseToken?: boolean; - externalPriceApiClientForcedNumerator?: number; - externalPriceApiClientForcedDenominator?: number; - externalPriceApiClientForcedFluctuation?: number; - baseTokenPricePollingIntervalMs?: number; - baseTokenAdjusterL1UpdateDeviationPercentage?: number; - } | null = null - ): Promise> { + public async killAndSpawnMainNode(configOverrides: MainNodeOptions | null = null): Promise { + if (this.mainNode != null) { + await this.mainNode.killAndWaitForShutdown(); + this.mainNode = null; + } + this.mainNode = await this.spawnMainNode(configOverrides); + } + + private async spawnMainNode(overrides: MainNodeOptions | null): Promise> { const env = this.env ?? process.env; const { fileConfig, pathToHome, options, logs } = this; diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index dc33a54e750..43a029bc264 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -69,7 +69,6 @@ testFees('Test fees', function () { let ethClientWeb3Url: string; let apiWeb3JsonRpcHttpUrl: string; let mainNodeSpawner: NodeSpawner; - let mainNode: Node; const fileConfig = shouldLoadConfigFromFile(); const pathToHome = path.join(__dirname, '../../../..'); @@ -124,7 +123,7 @@ testFees('Test fees', function () { baseTokenAddress }); - mainNode = await mainNodeSpawner.spawnMainNode(); + await mainNodeSpawner.killAndSpawnMainNode(); alice = testMaster.mainAccount(); tokenDetails = testMaster.environment().erc20Token; @@ -210,8 +209,7 @@ testFees('Test fees', function () { ]; for (const gasPrice of L1_GAS_PRICES_TO_TEST) { // For the sake of simplicity, we'll use the same pubdata price as the L1 gas price. - await mainNode.killAndWaitForShutdown(); - mainNode = await mainNodeSpawner.spawnMainNode({ + await mainNodeSpawner.killAndSpawnMainNode({ newL1GasPrice: gasPrice, newPubdataPrice: gasPrice }); @@ -252,9 +250,7 @@ testFees('Test fees', function () { test('Test gas price expected value', async () => { const receiver = ethers.Wallet.createRandom().address; const l1GasPrice = 2_000_000_000n; /// set to 2 gwei - - await mainNode.killAndWaitForShutdown(); - mainNode = await mainNodeSpawner.spawnMainNode({ + await mainNodeSpawner.killAndSpawnMainNode({ newL1GasPrice: l1GasPrice, newPubdataPrice: l1GasPrice }); @@ -287,9 +283,10 @@ testFees('Test fees', function () { console.log('feeParams', feeParams); console.log('receipt', receipt); - console.log('gas price', await alice._providerL2().getGasPrice()); + console.log('gas price'); console.log(await alice._providerL2().getFeeParams()); expect(receipt.gasPrice).toBe(BigInt(expectedConvertedGasPrice)); + expect(await alice._providerL2().getGasPrice()).toBe(BigInt(expectedConvertedGasPrice)); }); test('Test base token ratio fluctuations', async () => { @@ -297,8 +294,7 @@ testFees('Test fees', function () { if (isETHBasedChain) return; - await mainNode.killAndWaitForShutdown(); - mainNode = await mainNodeSpawner.spawnMainNode({ + await mainNodeSpawner.killAndSpawnMainNode({ newL1GasPrice: l1GasPrice, newPubdataPrice: l1GasPrice, externalPriceApiClientForcedNumerator: 300, @@ -369,8 +365,7 @@ testFees('Test fees', function () { // that the gasLimit is indeed over u32::MAX, which is the most important tested property. const requiredPubdataPrice = minimalL2GasPrice * 100_000n; - await mainNode.killAndWaitForShutdown(); - mainNode = await mainNodeSpawner.spawnMainNode({ + await mainNodeSpawner.killAndSpawnMainNode({ newL1GasPrice: requiredPubdataPrice, newPubdataPrice: requiredPubdataPrice }); @@ -415,11 +410,10 @@ testFees('Test fees', function () { afterAll(async () => { await testMaster.deinitialize(); - await mainNode.killAndWaitForShutdown(); // Returning the pubdata price to the default one // Spawning with no options restores defaults. - mainNode = await mainNodeSpawner.spawnMainNode(); - __ZKSYNC_TEST_CONTEXT_OWNER__.setL2NodePid(mainNode.proc.pid!); + await mainNodeSpawner.killAndSpawnMainNode(); + __ZKSYNC_TEST_CONTEXT_OWNER__.setL2NodePid(mainNodeSpawner.mainNode!.proc.pid!); }); }); From ef0e4ed5acab31b82738b38c56b912174e518fb9 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Mon, 14 Oct 2024 19:51:18 +0200 Subject: [PATCH 80/85] lint --- core/tests/ts-integration/tests/fees.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index b1856eab0ec..3512486993f 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -21,7 +21,7 @@ import { logsTestPath } from 'utils/build/logs'; import { sleep } from 'utils/build'; import { killPidWithAllChilds } from 'utils/build/kill'; import path from 'path'; -import { NodeSpawner, Node, NodeType } from '../src/utils'; +import { NodeSpawner } from '../src/utils'; import { sendTransfers } from '../src/context-owner'; import { Reporter } from '../src/reporter'; From 7026fa192638e9cf214cf54fd47f8f5eeb513ecf Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 15 Oct 2024 15:19:47 +0200 Subject: [PATCH 81/85] feat: nonce stable deposit of token sin integration test context-owner.ts --- .../tests/ts-integration/src/context-owner.ts | 150 ++++++++++-------- 1 file changed, 87 insertions(+), 63 deletions(-) diff --git a/core/tests/ts-integration/src/context-owner.ts b/core/tests/ts-integration/src/context-owner.ts index e77cdf1a053..14bf6ba470d 100644 --- a/core/tests/ts-integration/src/context-owner.ts +++ b/core/tests/ts-integration/src/context-owner.ts @@ -292,6 +292,7 @@ export class TestContextOwner { // Mint ERC20. const l1Erc20ABI = ['function mint(address to, uint256 amount)']; const l1Erc20Contract = new ethers.Contract(baseTokenAddress, l1Erc20ABI, this.mainEthersWallet); + const baseMintPromise = l1Erc20Contract .mint(this.mainSyncWallet.address, baseMintAmount, { nonce: nonce++, @@ -304,38 +305,40 @@ export class TestContextOwner { this.reporter.debug(`Nonce changed by 1 for ERC20 mint, new nonce: ${nonce}`); await baseMintPromise; - // Deposit base token if needed - const baseIsTransferred = true; - const baseDepositPromise = this.mainSyncWallet - .deposit({ - token: baseTokenAddress, - amount: l2erc20DepositAmount, - approveERC20: true, - approveBaseERC20: true, - approveBaseOverrides: { - nonce: nonce, - gasPrice - }, - approveOverrides: { - nonce: nonce + (ethIsBaseToken ? 0 : 1), // if eth is base, we don't need to approve base - gasPrice - }, - overrides: { - nonce: nonce + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1), // if base is transferred, we don't need to approve override - gasPrice - } - }) - .then((tx) => { - // Note: there is an `approve` tx, not listed here. - this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}`); - return tx.wait(); - }); - nonce = nonce + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1); - this.reporter.debug( - `Nonce changed by ${ - 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1) - } for ERC20 deposit, new nonce: ${nonce}` + l1TxPromises.push( + //infinite approval + this.mainSyncWallet + .approveERC20( + baseTokenAddress, + '115792089237316195423570985008687907853269984665640564039457584007913129639935', + { nonce: nonce++ } + ) + .then((tx) => { + this.reporter.debug( + `Sent ERC20 infinite approve transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}` + ); + return tx.wait(); + }) + ); + + l1TxPromises.push( + this.mainSyncWallet + .deposit({ + token: baseTokenAddress, + amount: l2erc20DepositAmount, + approveERC20: false, + approveBaseERC20: false, + overrides: { + nonce: nonce++, + gasPrice + } + }) + .then((tx) => { + this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}`); + return tx.wait(); + }) ); + this.reporter.debug(`Nonce changed by 2 for ERC20 deposit, new nonce: ${nonce}`); // Send base token on L1. const baseTokenTransfers = await sendTransfers( baseTokenAddress, @@ -347,7 +350,6 @@ export class TestContextOwner { this.reporter ); - l1TxPromises.push(baseDepositPromise); l1TxPromises.push(...baseTokenTransfers); this.reporter.debug(`Sent ${l1TxPromises.length} base token initial transactions on L1`); @@ -413,7 +415,6 @@ export class TestContextOwner { const erc20Token = this.env.erc20Token.l1Address; const erc20MintAmount = l2erc20DepositAmount * 100n; // Mint ERC20. - const baseIsTransferred = false; // we are not transferring the base const l1Erc20ABI = ['function mint(address to, uint256 amount)']; const l1Erc20Contract = new ethers.Contract(erc20Token, l1Erc20ABI, this.mainEthersWallet); const gasLimit = await l1Erc20Contract.mint.estimateGas(this.mainSyncWallet.address, erc20MintAmount); @@ -430,36 +431,60 @@ export class TestContextOwner { this.reporter.debug(`Nonce changed by 1 for ERC20 mint, new nonce: ${nonce}`); await erc20MintPromise; // Deposit ERC20. - const erc20DepositPromise = this.mainSyncWallet - .deposit({ - token: erc20Token, - amount: l2erc20DepositAmount, - approveERC20: true, - approveBaseERC20: true, - approveBaseOverrides: { - nonce: nonce, - gasPrice - }, - approveOverrides: { - nonce: nonce + (ethIsBaseToken ? 0 : 1), // if eth is base, we don't need to approve base - gasPrice - }, - overrides: { - nonce: nonce + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1), // if base is transferred, we don't need to approve override - gasPrice - } - }) - .then((tx) => { - // Note: there is an `approve` tx, not listed here. - this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, nonce: ${tx.nonce}`); - return tx.wait(); - }); - nonce = nonce + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1); - this.reporter.debug( - `Nonce changed by ${ - 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1) - } for ERC20 deposit, new nonce: ${nonce}` + if (!ethIsBaseToken) { + l1TxPromises.push( + //infinite approval + this.mainSyncWallet + .approveERC20( + baseTokenAddress, + '115792089237316195423570985008687907853269984665640564039457584007913129639935', + { nonce: nonce++ } + ) + .then((tx) => { + this.reporter.debug( + `Sent Base ERC20 infinite approve transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}` + ); + return tx.wait(); + }) + ); + } + + // we are not transferring the base + l1TxPromises.push( + //infinite approval + this.mainSyncWallet + .approveERC20( + erc20Token, + '115792089237316195423570985008687907853269984665640564039457584007913129639935', + { nonce: nonce++ } + ) + .then((tx) => { + this.reporter.debug( + `Sent Token ERC20 infinite approve transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}` + ); + return tx.wait(); + }) ); + + l1TxPromises.push( + this.mainSyncWallet + .deposit({ + token: erc20Token, + amount: l2erc20DepositAmount, + approveERC20: false, + approveBaseERC20: false, + overrides: { + nonce: nonce++, + gasPrice + } + }) + .then((tx) => { + this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, nonce: ${tx.nonce}`); + return tx.wait(); + }) + ); + + this.reporter.debug(`Nonce changed for ERC20 deposit, new nonce: ${nonce}`); // Send ETH on L1. const ethTransfers = await sendTransfers( zksync.utils.ETH_ADDRESS, @@ -495,7 +520,6 @@ export class TestContextOwner { this.reporter ); - l1TxPromises.push(erc20DepositPromise); l1TxPromises.push(...ethTransfers); l1TxPromises.push(...erc20Transfers); l1TxPromises.push(...baseErc20Transfers); From 51482503591c4bd261e1846db7606701f7eb0b06 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Tue, 15 Oct 2024 15:45:20 +0200 Subject: [PATCH 82/85] Revert "feat: nonce stable deposit of token sin integration test context-owner.ts" This reverts commit 7026fa192638e9cf214cf54fd47f8f5eeb513ecf. --- .../tests/ts-integration/src/context-owner.ts | 150 ++++++++---------- 1 file changed, 63 insertions(+), 87 deletions(-) diff --git a/core/tests/ts-integration/src/context-owner.ts b/core/tests/ts-integration/src/context-owner.ts index 14bf6ba470d..e77cdf1a053 100644 --- a/core/tests/ts-integration/src/context-owner.ts +++ b/core/tests/ts-integration/src/context-owner.ts @@ -292,7 +292,6 @@ export class TestContextOwner { // Mint ERC20. const l1Erc20ABI = ['function mint(address to, uint256 amount)']; const l1Erc20Contract = new ethers.Contract(baseTokenAddress, l1Erc20ABI, this.mainEthersWallet); - const baseMintPromise = l1Erc20Contract .mint(this.mainSyncWallet.address, baseMintAmount, { nonce: nonce++, @@ -305,40 +304,38 @@ export class TestContextOwner { this.reporter.debug(`Nonce changed by 1 for ERC20 mint, new nonce: ${nonce}`); await baseMintPromise; - l1TxPromises.push( - //infinite approval - this.mainSyncWallet - .approveERC20( - baseTokenAddress, - '115792089237316195423570985008687907853269984665640564039457584007913129639935', - { nonce: nonce++ } - ) - .then((tx) => { - this.reporter.debug( - `Sent ERC20 infinite approve transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}` - ); - return tx.wait(); - }) - ); - - l1TxPromises.push( - this.mainSyncWallet - .deposit({ - token: baseTokenAddress, - amount: l2erc20DepositAmount, - approveERC20: false, - approveBaseERC20: false, - overrides: { - nonce: nonce++, - gasPrice - } - }) - .then((tx) => { - this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}`); - return tx.wait(); - }) + // Deposit base token if needed + const baseIsTransferred = true; + const baseDepositPromise = this.mainSyncWallet + .deposit({ + token: baseTokenAddress, + amount: l2erc20DepositAmount, + approveERC20: true, + approveBaseERC20: true, + approveBaseOverrides: { + nonce: nonce, + gasPrice + }, + approveOverrides: { + nonce: nonce + (ethIsBaseToken ? 0 : 1), // if eth is base, we don't need to approve base + gasPrice + }, + overrides: { + nonce: nonce + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1), // if base is transferred, we don't need to approve override + gasPrice + } + }) + .then((tx) => { + // Note: there is an `approve` tx, not listed here. + this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}`); + return tx.wait(); + }); + nonce = nonce + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1); + this.reporter.debug( + `Nonce changed by ${ + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1) + } for ERC20 deposit, new nonce: ${nonce}` ); - this.reporter.debug(`Nonce changed by 2 for ERC20 deposit, new nonce: ${nonce}`); // Send base token on L1. const baseTokenTransfers = await sendTransfers( baseTokenAddress, @@ -350,6 +347,7 @@ export class TestContextOwner { this.reporter ); + l1TxPromises.push(baseDepositPromise); l1TxPromises.push(...baseTokenTransfers); this.reporter.debug(`Sent ${l1TxPromises.length} base token initial transactions on L1`); @@ -415,6 +413,7 @@ export class TestContextOwner { const erc20Token = this.env.erc20Token.l1Address; const erc20MintAmount = l2erc20DepositAmount * 100n; // Mint ERC20. + const baseIsTransferred = false; // we are not transferring the base const l1Erc20ABI = ['function mint(address to, uint256 amount)']; const l1Erc20Contract = new ethers.Contract(erc20Token, l1Erc20ABI, this.mainEthersWallet); const gasLimit = await l1Erc20Contract.mint.estimateGas(this.mainSyncWallet.address, erc20MintAmount); @@ -431,60 +430,36 @@ export class TestContextOwner { this.reporter.debug(`Nonce changed by 1 for ERC20 mint, new nonce: ${nonce}`); await erc20MintPromise; // Deposit ERC20. - if (!ethIsBaseToken) { - l1TxPromises.push( - //infinite approval - this.mainSyncWallet - .approveERC20( - baseTokenAddress, - '115792089237316195423570985008687907853269984665640564039457584007913129639935', - { nonce: nonce++ } - ) - .then((tx) => { - this.reporter.debug( - `Sent Base ERC20 infinite approve transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}` - ); - return tx.wait(); - }) - ); - } - - // we are not transferring the base - l1TxPromises.push( - //infinite approval - this.mainSyncWallet - .approveERC20( - erc20Token, - '115792089237316195423570985008687907853269984665640564039457584007913129639935', - { nonce: nonce++ } - ) - .then((tx) => { - this.reporter.debug( - `Sent Token ERC20 infinite approve transaction. Hash: ${tx.hash}, tx nonce: ${tx.nonce}` - ); - return tx.wait(); - }) - ); - - l1TxPromises.push( - this.mainSyncWallet - .deposit({ - token: erc20Token, - amount: l2erc20DepositAmount, - approveERC20: false, - approveBaseERC20: false, - overrides: { - nonce: nonce++, - gasPrice - } - }) - .then((tx) => { - this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, nonce: ${tx.nonce}`); - return tx.wait(); - }) + const erc20DepositPromise = this.mainSyncWallet + .deposit({ + token: erc20Token, + amount: l2erc20DepositAmount, + approveERC20: true, + approveBaseERC20: true, + approveBaseOverrides: { + nonce: nonce, + gasPrice + }, + approveOverrides: { + nonce: nonce + (ethIsBaseToken ? 0 : 1), // if eth is base, we don't need to approve base + gasPrice + }, + overrides: { + nonce: nonce + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1), // if base is transferred, we don't need to approve override + gasPrice + } + }) + .then((tx) => { + // Note: there is an `approve` tx, not listed here. + this.reporter.debug(`Sent ERC20 deposit transaction. Hash: ${tx.hash}, nonce: ${tx.nonce}`); + return tx.wait(); + }); + nonce = nonce + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1); + this.reporter.debug( + `Nonce changed by ${ + 1 + (ethIsBaseToken ? 0 : 1) + (baseIsTransferred ? 0 : 1) + } for ERC20 deposit, new nonce: ${nonce}` ); - - this.reporter.debug(`Nonce changed for ERC20 deposit, new nonce: ${nonce}`); // Send ETH on L1. const ethTransfers = await sendTransfers( zksync.utils.ETH_ADDRESS, @@ -520,6 +495,7 @@ export class TestContextOwner { this.reporter ); + l1TxPromises.push(erc20DepositPromise); l1TxPromises.push(...ethTransfers); l1TxPromises.push(...erc20Transfers); l1TxPromises.push(...baseErc20Transfers); From f05a21a58ae43610bee13ea338c37fa376465099 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 16 Oct 2024 11:49:43 +0200 Subject: [PATCH 83/85] feat: less stupid yaml config override code --- core/tests/ts-integration/src/utils.ts | 27 +++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/core/tests/ts-integration/src/utils.ts b/core/tests/ts-integration/src/utils.ts index 28996e2015c..2167da81396 100644 --- a/core/tests/ts-integration/src/utils.ts +++ b/core/tests/ts-integration/src/utils.ts @@ -6,6 +6,7 @@ import * as utils from 'utils'; import fs from 'node:fs/promises'; import * as zksync from 'zksync-ethers'; import * as fsSync from 'fs'; +import YAML from 'yaml'; // executes a command in background and returns a child process handle // by default pipes data to parent's stdio but this can be overridden @@ -298,21 +299,25 @@ export class NodeSpawner { if (this.generalConfigPath == void 0) throw new Error('Trying to set property in config while not in file mode'); const generalConfig = fsSync.readFileSync(this.generalConfigPath, 'utf8'); + const parsed = YAML.parse(generalConfig); - // Define the regex pattern to check if the property already exists - const propertyRegex = new RegExp(`(^\\s*${property}:\\s*\\d+(\\.\\d+)?$)`, 'm'); - const gasAdjusterRegex = new RegExp(`(^\\s*${parentProperty}:.*$)`, 'gm'); - - let newGeneralConfig; - - if (propertyRegex.test(generalConfig)) { - // If the property exists, modify its value - newGeneralConfig = generalConfig.replace(propertyRegex, ` ${property}: ${value}`); + // TODO FIX THIS SHITTY CODE + if (parentProperty == 'gas_adjuster') { + if (parsed['eth'][parentProperty] == null) { + console.log(parsed); + throw new Error(`No eth->${parentProperty} config section in general.yaml`); + } + parsed['eth'][parentProperty][property] = value; } else { - // If the property does not exist, add it under the gas_adjuster section - newGeneralConfig = generalConfig.replace(gasAdjusterRegex, `$1\n ${property}: ${value}`); + if (parsed[parentProperty] == null) { + console.log(parsed); + throw new Error(`No ${parentProperty} config section in general.yaml`); + } + parsed[parentProperty][property] = value; } + const newGeneralConfig = YAML.stringify(parsed); + fsSync.writeFileSync(this.generalConfigPath, newGeneralConfig, 'utf8'); } From 9ebfc339e83effb063e3224f40f02ab9b66bbf1e Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 16 Oct 2024 16:30:53 +0200 Subject: [PATCH 84/85] fix: distribute eth to token_multplier_setter --- zkstack_cli/crates/zkstack/src/commands/chain/common.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zkstack_cli/crates/zkstack/src/commands/chain/common.rs b/zkstack_cli/crates/zkstack/src/commands/chain/common.rs index e0aa0b4e047..0c35b3ee4fe 100644 --- a/zkstack_cli/crates/zkstack/src/commands/chain/common.rs +++ b/zkstack_cli/crates/zkstack/src/commands/chain/common.rs @@ -27,6 +27,9 @@ pub async fn distribute_eth( if let Some(deployer) = chain_wallets.deployer { addresses.push(deployer.address) } + if let Some(setter) = chain_wallets.token_multiplier_setter { + addresses.push(setter.address) + } common::ethereum::distribute_eth( wallets.operator, addresses, From 509dab38c5d4004c49acae5b650c654de4ef42d7 Mon Sep 17 00:00:00 2001 From: Artur Puzio Date: Wed, 16 Oct 2024 17:00:04 +0200 Subject: [PATCH 85/85] fix: Add 1 block wait to gas price test --- core/tests/ts-integration/tests/fees.test.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/tests/ts-integration/tests/fees.test.ts b/core/tests/ts-integration/tests/fees.test.ts index 3512486993f..44408d087b5 100644 --- a/core/tests/ts-integration/tests/fees.test.ts +++ b/core/tests/ts-integration/tests/fees.test.ts @@ -255,12 +255,16 @@ testFees('Test fees', function () { newPubdataPrice: l1GasPrice }); - const receipt = await ( - await alice.sendTransaction({ + const doTxToReceiver = () => + alice.sendTransaction({ to: receiver, value: BigInt(1) - }) - ).wait(); + }); + + //wait 1 miniblock so the multiplier gets updated + await doTxToReceiver().then((tx) => tx.wait(1)); + + const receipt = await doTxToReceiver().then((tx) => tx.wait()); const feeParams = await alice._providerL2().getFeeParams(); const feeConfig = feeParams.V2.config; @@ -283,7 +287,7 @@ testFees('Test fees', function () { console.log('feeParams', feeParams); console.log('receipt', receipt); - console.log('gas price'); + console.log('gas price', await alice._providerL2().getGasPrice()); console.log(await alice._providerL2().getFeeParams()); expect(receipt.gasPrice).toBe(BigInt(expectedConvertedGasPrice)); expect(await alice._providerL2().getGasPrice()).toBe(BigInt(expectedConvertedGasPrice));