Skip to content

Commit

Permalink
fix: make set token multiplier optional (#2696)
Browse files Browse the repository at this point in the history
For backwards compatibility make setting token multiplier on L1
optional. If private key for token multiplier setter is not provided, L1
quote update will be skipped.
  • Loading branch information
ischasny authored Aug 20, 2024
1 parent 2f456f0 commit 16dff4f
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 69 deletions.
87 changes: 43 additions & 44 deletions core/node/base_token_adjuster/src/base_token_ratio_persister.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::{cmp::max, fmt::Debug, sync::Arc, time::Duration};
use anyhow::Context as _;
use tokio::{sync::watch, time::sleep};
use zksync_config::configs::base_token_adjuster::BaseTokenAdjusterConfig;
use zksync_contracts::chain_admin_contract;
use zksync_dal::{ConnectionPool, Core, CoreDal};
use zksync_eth_client::{BoundEthInterface, Options};
use zksync_external_price_api::PriceAPIClient;
Expand All @@ -15,18 +14,23 @@ use zksync_types::{
Address, U256,
};

#[derive(Debug, Clone)]
pub struct BaseTokenRatioPersisterL1Params {
pub eth_client: Box<dyn BoundEthInterface>,
pub gas_adjuster: Arc<dyn TxParamsProvider>,
pub token_multiplier_setter_account_address: Address,
pub chain_admin_contract: Contract,
pub diamond_proxy_contract_address: Address,
pub chain_admin_contract_address: Option<Address>,
}

#[derive(Debug, Clone)]
pub struct BaseTokenRatioPersister {
pool: ConnectionPool<Core>,
config: BaseTokenAdjusterConfig,
base_token_address: Address,
price_api_client: Arc<dyn PriceAPIClient>,
eth_client: Box<dyn BoundEthInterface>,
gas_adjuster: Arc<dyn TxParamsProvider>,
token_multiplier_setter_account_address: Address,
chain_admin_contract: Contract,
diamond_proxy_contract_address: Address,
chain_admin_contract_address: Option<Address>,
l1_params: Option<BaseTokenRatioPersisterL1Params>,
}

impl BaseTokenRatioPersister {
Expand All @@ -36,25 +40,14 @@ impl BaseTokenRatioPersister {
config: BaseTokenAdjusterConfig,
base_token_address: Address,
price_api_client: Arc<dyn PriceAPIClient>,
eth_client: Box<dyn BoundEthInterface>,
gas_adjuster: Arc<dyn TxParamsProvider>,
token_multiplier_setter_account_address: Address,
diamond_proxy_contract_address: Address,
chain_admin_contract_address: Option<Address>,
l1_params: Option<BaseTokenRatioPersisterL1Params>,
) -> Self {
let chain_admin_contract = chain_admin_contract();

Self {
pool,
config,
base_token_address,
price_api_client,
eth_client,
gas_adjuster,
token_multiplier_setter_account_address,
chain_admin_contract,
diamond_proxy_contract_address,
chain_admin_contract_address,
l1_params,
}
}

Expand Down Expand Up @@ -90,6 +83,10 @@ impl BaseTokenRatioPersister {
let new_ratio = self.retry_fetch_ratio().await?;
self.persist_ratio(new_ratio).await?;

let Some(l1_params) = &self.l1_params else {
return Ok(());
};

let max_attempts = self.config.l1_tx_sending_max_attempts;
let sleep_duration = self.config.l1_tx_sending_sleep_duration();
let mut result: anyhow::Result<()> = Ok(());
Expand All @@ -98,30 +95,30 @@ impl BaseTokenRatioPersister {

for attempt in 0..max_attempts {
let (base_fee_per_gas, priority_fee_per_gas) =
self.get_eth_fees(prev_base_fee_per_gas, prev_priority_fee_per_gas);
self.get_eth_fees(l1_params, prev_base_fee_per_gas, prev_priority_fee_per_gas);

result = self
.send_ratio_to_l1(new_ratio, base_fee_per_gas, priority_fee_per_gas)
.send_ratio_to_l1(l1_params, new_ratio, base_fee_per_gas, priority_fee_per_gas)
.await;
if let Some(err) = result.as_ref().err() {
tracing::info!(
"Failed to update base token multiplier on L1, attempt {}, base_fee_per_gas {}, priority_fee_per_gas {}: {}",
attempt + 1,
base_fee_per_gas,
priority_fee_per_gas,
err
);
"Failed to update base token multiplier on L1, attempt {}, base_fee_per_gas {}, priority_fee_per_gas {}: {}",
attempt + 1,
base_fee_per_gas,
priority_fee_per_gas,
err
);
tokio::time::sleep(sleep_duration).await;
prev_base_fee_per_gas = Some(base_fee_per_gas);
prev_priority_fee_per_gas = Some(priority_fee_per_gas);
} else {
tracing::info!(
"Updated base token multiplier on L1: numerator {}, denominator {}, base_fee_per_gas {}, priority_fee_per_gas {}",
new_ratio.numerator.get(),
new_ratio.denominator.get(),
base_fee_per_gas,
priority_fee_per_gas
);
"Updated base token multiplier on L1: numerator {}, denominator {}, base_fee_per_gas {}, priority_fee_per_gas {}",
new_ratio.numerator.get(),
new_ratio.denominator.get(),
base_fee_per_gas,
priority_fee_per_gas
);
return result;
}
}
Expand All @@ -130,13 +127,14 @@ impl BaseTokenRatioPersister {

fn get_eth_fees(
&self,
l1_params: &BaseTokenRatioPersisterL1Params,
prev_base_fee_per_gas: Option<u64>,
prev_priority_fee_per_gas: Option<u64>,
) -> (u64, u64) {
// Use get_blob_tx_base_fee here instead of get_base_fee to optimise for fast inclusion.
// get_base_fee might cause the transaction to be stuck in the mempool for 10+ minutes.
let mut base_fee_per_gas = self.gas_adjuster.as_ref().get_blob_tx_base_fee();
let mut priority_fee_per_gas = self.gas_adjuster.as_ref().get_priority_fee();
let mut base_fee_per_gas = l1_params.gas_adjuster.as_ref().get_blob_tx_base_fee();
let mut priority_fee_per_gas = l1_params.gas_adjuster.as_ref().get_priority_fee();
if let Some(x) = prev_priority_fee_per_gas {
// Increase `priority_fee_per_gas` by at least 20% to prevent "replacement transaction under-priced" error.
priority_fee_per_gas = max(priority_fee_per_gas, (x * 6) / 5 + 1);
Expand Down Expand Up @@ -213,30 +211,31 @@ impl BaseTokenRatioPersister {

async fn send_ratio_to_l1(
&self,
l1_params: &BaseTokenRatioPersisterL1Params,
api_ratio: BaseTokenAPIRatio,
base_fee_per_gas: u64,
priority_fee_per_gas: u64,
) -> anyhow::Result<()> {
let fn_set_token_multiplier = self
let fn_set_token_multiplier = l1_params
.chain_admin_contract
.function("setTokenMultiplier")
.context("`setTokenMultiplier` function must be present in the ChainAdmin contract")?;

let calldata = fn_set_token_multiplier
.encode_input(
&(
Token::Address(self.diamond_proxy_contract_address),
Token::Address(l1_params.diamond_proxy_contract_address),
Token::Uint(api_ratio.numerator.get().into()),
Token::Uint(api_ratio.denominator.get().into()),
)
.into_tokens(),
)
.context("failed encoding `setTokenMultiplier` input")?;

let nonce = (*self.eth_client)
let nonce = (*l1_params.eth_client)
.as_ref()
.nonce_at_for_account(
self.token_multiplier_setter_account_address,
l1_params.token_multiplier_setter_account_address,
BlockNumber::Pending,
)
.await
Expand All @@ -251,17 +250,17 @@ impl BaseTokenRatioPersister {
..Default::default()
};

let signed_tx = self
let signed_tx = l1_params
.eth_client
.sign_prepared_tx_for_addr(
calldata,
self.chain_admin_contract_address.unwrap(),
l1_params.chain_admin_contract_address.unwrap(),
options,
)
.await
.context("cannot sign a `setTokenMultiplier` transaction")?;

let hash = (*self.eth_client)
let hash = (*l1_params.eth_client)
.as_ref()
.send_raw_tx(signed_tx.raw_tx)
.await
Expand All @@ -270,7 +269,7 @@ impl BaseTokenRatioPersister {
let max_attempts = self.config.l1_receipt_checking_max_attempts;
let sleep_duration = self.config.l1_receipt_checking_sleep_duration();
for _i in 0..max_attempts {
let maybe_receipt = (*self.eth_client)
let maybe_receipt = (*l1_params.eth_client)
.as_ref()
.tx_receipt(hash)
.await
Expand Down
2 changes: 1 addition & 1 deletion core/node/base_token_adjuster/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub use self::{
base_token_ratio_persister::BaseTokenRatioPersister,
base_token_ratio_persister::{BaseTokenRatioPersister, BaseTokenRatioPersisterL1Params},
base_token_ratio_provider::{DBBaseTokenRatioProvider, NoOpRatioProvider},
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use zksync_base_token_adjuster::BaseTokenRatioPersister;
use zksync_base_token_adjuster::{BaseTokenRatioPersister, BaseTokenRatioPersisterL1Params};
use zksync_config::{
configs::{base_token_adjuster::BaseTokenAdjusterConfig, wallets::Wallets},
ContractsConfig,
};
use zksync_contracts::chain_admin_contract;
use zksync_eth_client::clients::PKSigningClient;
use zksync_types::L1ChainId;

Expand Down Expand Up @@ -81,37 +82,39 @@ impl WiringLayer for BaseTokenRatioPersisterLayer {
.contracts_config
.base_token_addr
.expect("base token address is not set");
let diamond_proxy_contract_address = self.contracts_config.diamond_proxy_addr;
let chain_admin_contract_address = self.contracts_config.chain_admin_addr;
let token_multiplier_setter_wallet = self
.wallets_config
.token_multiplier_setter
.expect("base token adjuster wallet is not set")
.wallet;

let tms_private_key = token_multiplier_setter_wallet.private_key();
let tms_address = token_multiplier_setter_wallet.address();
let EthInterfaceResource(query_client) = input.eth_client;
let l1_params =
self.wallets_config
.token_multiplier_setter
.map(|token_multiplier_setter| {
let tms_private_key = token_multiplier_setter.wallet.private_key();
let tms_address = token_multiplier_setter.wallet.address();
let EthInterfaceResource(query_client) = input.eth_client;

let signing_client = PKSigningClient::new_raw(
tms_private_key.clone(),
self.contracts_config.diamond_proxy_addr,
self.config.default_priority_fee_per_gas,
#[allow(clippy::useless_conversion)]
self.l1_chain_id.into(),
query_client.clone().for_component("base_token_adjuster"),
);
let signing_client = PKSigningClient::new_raw(
tms_private_key.clone(),
self.contracts_config.diamond_proxy_addr,
self.config.default_priority_fee_per_gas,
#[allow(clippy::useless_conversion)]
self.l1_chain_id.into(),
query_client.clone().for_component("base_token_adjuster"),
);
BaseTokenRatioPersisterL1Params {
eth_client: Box::new(signing_client),
gas_adjuster: input.tx_params.0,
token_multiplier_setter_account_address: tms_address,
chain_admin_contract: chain_admin_contract(),
diamond_proxy_contract_address: self.contracts_config.diamond_proxy_addr,
chain_admin_contract_address: self.contracts_config.chain_admin_addr,
}
});

let persister = BaseTokenRatioPersister::new(
master_pool,
self.config,
base_token_addr,
price_api_client.0,
Box::new(signing_client),
input.tx_params.0,
tms_address,
diamond_proxy_contract_address,
chain_admin_contract_address,
l1_params,
);

Ok(Output { persister })
Expand Down

0 comments on commit 16dff4f

Please sign in to comment.