diff --git a/core/bin/zksync_api/src/fee_ticker/fee_token_validator.rs b/core/bin/zksync_api/src/fee_ticker/fee_token_validator.rs
index 592a1d9905..2aed3e5af6 100644
--- a/core/bin/zksync_api/src/fee_ticker/fee_token_validator.rs
+++ b/core/bin/zksync_api/src/fee_ticker/fee_token_validator.rs
@@ -2,7 +2,7 @@
//! an entity which decides whether certain ERC20 token is suitable for paying fees.
// Built-in uses
-use std::{collections::HashMap, str::FromStr};
+use std::collections::{HashMap, HashSet};
// Workspace uses
use zksync_types::{
tokens::{Token, TokenLike},
@@ -15,12 +15,18 @@ use crate::utils::token_db_cache::TokenDBCache;
#[derive(Debug, Clone)]
pub(crate) struct FeeTokenValidator {
tokens_cache: TokenCacheWrapper,
+ /// List of tokens that aren't accepted to pay fees in.
+ disabled_tokens: HashSet
,
}
impl FeeTokenValidator {
- pub(crate) fn new(cache: impl Into) -> Self {
+ pub(crate) fn new(
+ cache: impl Into,
+ disabled_tokens: HashSet,
+ ) -> Self {
Self {
tokens_cache: cache.into(),
+ disabled_tokens,
}
}
@@ -40,12 +46,8 @@ impl FeeTokenValidator {
// Later we'll check Uniswap trading volume for tokens. That's why this function is already `async` even
// though it's not really `async` at this moment.
- let not_supported_tokens = &[
- Address::from_str("38A2fDc11f526Ddd5a607C1F251C065f40fBF2f7").unwrap(), // PHNX (PhoenixDAO)
- ];
-
if let Some(token) = token {
- let not_acceptable = not_supported_tokens.iter().any(|&t| t == token.address);
+ let not_acceptable = self.disabled_tokens.contains(&token.address);
Ok(!not_acceptable)
} else {
// Unknown tokens aren't suitable for our needs, obviously.
@@ -84,6 +86,8 @@ impl TokenCacheWrapper {
#[cfg(test)]
mod tests {
use super::*;
+ use std::collections::HashSet;
+ use std::str::FromStr;
#[tokio::test]
async fn check_tokens() {
@@ -98,7 +102,10 @@ mod tests {
tokens.insert(TokenLike::Address(dai_token_address), dai_token);
tokens.insert(TokenLike::Address(phnx_token_address), phnx_token);
- let validator = FeeTokenValidator::new(tokens);
+ let mut disabled_tokens = HashSet::new();
+ disabled_tokens.insert(phnx_token_address);
+
+ let validator = FeeTokenValidator::new(tokens, disabled_tokens);
let dai_allowed = validator
.token_allowed(TokenLike::Address(dai_token_address))
diff --git a/core/bin/zksync_api/src/fee_ticker/mod.rs b/core/bin/zksync_api/src/fee_ticker/mod.rs
index 5ed6e76c03..e978165ca2 100644
--- a/core/bin/zksync_api/src/fee_ticker/mod.rs
+++ b/core/bin/zksync_api/src/fee_ticker/mod.rs
@@ -4,7 +4,7 @@
//! `( zkp cost of chunk * number of chunks + gas price of transaction) * token risk factor / cost of token is usd`
// Built-in deps
-use std::collections::HashMap;
+use std::collections::{HashMap, HashSet};
// External deps
use bigdecimal::BigDecimal;
use futures::{
@@ -19,7 +19,7 @@ use num::{
use serde::{Deserialize, Serialize};
use tokio::task::JoinHandle;
// Workspace deps
-use zksync_config::TokenPriceSource;
+use zksync_config::{FeeTickerOptions, TokenPriceSource};
use zksync_storage::ConnectionPool;
use zksync_types::{
Address, ChangePubKeyOp, Token, TokenId, TokenLike, TransferOp, TransferToNewOp, TxFeeTypes,
@@ -142,7 +142,7 @@ pub struct TickerConfig {
zkp_cost_chunk_usd: Ratio,
gas_cost_tx: GasOperationsCost,
tokens_risk_factors: HashMap>,
- not_subsidized_tokens: Vec,
+ not_subsidized_tokens: HashSet,
}
#[derive(Debug, PartialEq, Eq)]
@@ -180,28 +180,27 @@ struct FeeTicker {
#[must_use]
pub fn run_ticker_task(
- token_price_source: TokenPriceSource,
- not_subsidized_tokens: Vec,
- fast_processing_coeff: f64,
db_pool: ConnectionPool,
tricker_requests: Receiver,
) -> JoinHandle<()> {
+ let config = FeeTickerOptions::from_env();
+
let ticker_config = TickerConfig {
zkp_cost_chunk_usd: Ratio::from_integer(BigUint::from(10u32).pow(3u32)).inv(),
- gas_cost_tx: GasOperationsCost::from_constants(fast_processing_coeff),
+ gas_cost_tx: GasOperationsCost::from_constants(config.fast_processing_coeff),
tokens_risk_factors: HashMap::new(),
- not_subsidized_tokens,
+ not_subsidized_tokens: config.not_subsidized_tokens,
};
let cache = TokenDBCache::new(db_pool.clone());
- let validator = FeeTokenValidator::new(cache);
+ let validator = FeeTokenValidator::new(cache, config.disabled_tokens);
let client = reqwest::ClientBuilder::new()
.timeout(CONNECTION_TIMEOUT)
.connect_timeout(CONNECTION_TIMEOUT)
.build()
.expect("Failed to build reqwest::Client");
- match token_price_source {
+ match config.token_price_source {
TokenPriceSource::CoinMarketCap { base_url } => {
let token_price_api = CoinMarketCapAPI::new(client, base_url);
@@ -309,10 +308,7 @@ impl FeeTicker {
/// Returns `true` if the token is subsidized.
async fn is_token_subsidized(&mut self, token: Token) -> bool {
- self.config
- .not_subsidized_tokens
- .iter()
- .all(|&t| t != token.address)
+ !self.config.not_subsidized_tokens.contains(&token.address)
}
async fn get_fee_from_ticker_in_wei(
diff --git a/core/bin/zksync_api/src/fee_ticker/tests.rs b/core/bin/zksync_api/src/fee_ticker/tests.rs
index ec7d99d811..776765ad0f 100644
--- a/core/bin/zksync_api/src/fee_ticker/tests.rs
+++ b/core/bin/zksync_api/src/fee_ticker/tests.rs
@@ -89,7 +89,9 @@ fn get_test_ticker_config() -> TickerConfig {
.collect(),
not_subsidized_tokens: vec![
Address::from_str("34083bbd70d394110487feaa087da875a54624ec").unwrap(),
- ],
+ ]
+ .into_iter()
+ .collect(),
}
}
@@ -155,7 +157,7 @@ fn format_with_dot(num: &Ratio, precision: usize) -> String {
#[test]
fn test_ticker_formula() {
- let validator = FeeTokenValidator::new(HashMap::new());
+ let validator = FeeTokenValidator::new(HashMap::new(), Default::default());
let config = get_test_ticker_config();
let mut ticker = FeeTicker::new(
@@ -251,7 +253,7 @@ fn test_ticker_formula() {
#[test]
fn test_fee_for_unsubsidized_tokens() {
- let validator = FeeTokenValidator::new(HashMap::new());
+ let validator = FeeTokenValidator::new(HashMap::new(), Default::default());
let config = get_test_ticker_config();
let mut ticker = FeeTicker::new(
diff --git a/core/bin/zksync_api/src/lib.rs b/core/bin/zksync_api/src/lib.rs
index 43236ebc01..78d7b63084 100644
--- a/core/bin/zksync_api/src/lib.rs
+++ b/core/bin/zksync_api/src/lib.rs
@@ -2,7 +2,7 @@
use crate::{api_server::start_api_server, fee_ticker::run_ticker_task};
use futures::channel::mpsc;
-use zksync_config::{AdminServerOptions, ConfigurationOptions, FeeTickerOptions};
+use zksync_config::{AdminServerOptions, ConfigurationOptions};
use zksync_storage::ConnectionPool;
pub mod api_server;
@@ -23,15 +23,8 @@ pub fn run_api(
let config_options = ConfigurationOptions::from_env();
let admin_server_options = AdminServerOptions::from_env();
- let fee_ticker_options = FeeTickerOptions::from_env();
- let ticker_task = run_ticker_task(
- config_options.token_price_source.clone(),
- fee_ticker_options.not_subsidized_tokens,
- config_options.ticker_fast_processing_coeff,
- connection_pool.clone(),
- ticker_request_receiver,
- );
+ let ticker_task = run_ticker_task(connection_pool.clone(), ticker_request_receiver);
start_api_server(
connection_pool,
diff --git a/core/lib/config/src/lib.rs b/core/lib/config/src/lib.rs
index 111bbebdd8..4dfc1ac6f5 100644
--- a/core/lib/config/src/lib.rs
+++ b/core/lib/config/src/lib.rs
@@ -1,9 +1,9 @@
// Built-in deps
-use std::{env, net::SocketAddr, str::FromStr, time::Duration};
+use std::{collections::HashSet, env, net::SocketAddr, str::FromStr, time::Duration};
// External uses
use url::Url;
// Workspace uses
-use zksync_basic_types::{H160, H256};
+use zksync_basic_types::{Address, H256};
use zksync_utils::{get_env, parse_env, parse_env_if_exists, parse_env_with};
// Local uses
@@ -133,6 +133,37 @@ impl MiniblockTimings {
}
}
+/// Configuration options related to fee ticker.
+#[derive(Debug)]
+pub struct FeeTickerOptions {
+ /// Source to fetch token prices from (e.g. CoinGecko or coinmarketcap).
+ pub token_price_source: TokenPriceSource,
+ /// Fee increase coefficient for fast processing of withdrawal.
+ pub fast_processing_coeff: f64,
+ /// List of the tokens that aren't acceptable for paying fee in.
+ pub disabled_tokens: HashSet,
+ /// Tokens for which subsidies are disabled.
+ pub not_subsidized_tokens: HashSet,
+}
+
+impl FeeTickerOptions {
+ fn comma_separated_addresses(name: &str) -> HashSet {
+ get_env(name)
+ .split(',')
+ .map(|p| p.parse().unwrap())
+ .collect()
+ }
+
+ pub fn from_env() -> Self {
+ Self {
+ token_price_source: TokenPriceSource::from_env(),
+ fast_processing_coeff: parse_env("TICKER_FAST_PROCESSING_COEFF"),
+ disabled_tokens: Self::comma_separated_addresses("TICKER_DISABLED_TOKENS"),
+ not_subsidized_tokens: Self::comma_separated_addresses("NOT_SUBSIDIZED_TOKENS"),
+ }
+ }
+}
+
#[derive(Debug, Clone)]
pub struct ConfigurationOptions {
pub rest_api_server_address: SocketAddr,
@@ -142,10 +173,10 @@ pub struct ConfigurationOptions {
pub core_server_url: String,
pub web3_url: String,
pub genesis_tx_hash: H256,
- pub contract_eth_addr: H160,
- pub governance_eth_addr: H160,
- pub operator_fee_eth_addr: H160,
- pub operator_commit_eth_addr: H160,
+ pub contract_eth_addr: Address,
+ pub governance_eth_addr: Address,
+ pub operator_fee_eth_addr: Address,
+ pub operator_commit_eth_addr: Address,
pub operator_private_key: Option,
pub chain_id: u8,
pub gas_price_factor: f64,
@@ -159,10 +190,7 @@ pub struct ConfigurationOptions {
pub idle_provers: u32,
pub miniblock_timings: MiniblockTimings,
pub prometheus_export_port: u16,
- pub token_price_source: TokenPriceSource,
pub witness_generators: usize,
- /// Fee increase coefficient for fast processing of withdrawal.
- pub ticker_fast_processing_coeff: f64,
pub forced_exit_minimum_account_age: Duration,
pub enforce_pubkey_change_fee: bool,
}
@@ -213,9 +241,7 @@ impl ConfigurationOptions {
idle_provers: parse_env("IDLE_PROVERS"),
miniblock_timings: MiniblockTimings::from_env(),
prometheus_export_port: parse_env("PROMETHEUS_EXPORT_PORT"),
- token_price_source: TokenPriceSource::from_env(),
witness_generators: parse_env("WITNESS_GENERATORS"),
- ticker_fast_processing_coeff: parse_env("TICKER_FAST_PROCESSING_COEFF"),
forced_exit_minimum_account_age,
enforce_pubkey_change_fee: parse_env_if_exists("ENFORCE_PUBKEY_CHANGE_FEE")
.unwrap_or(true),
@@ -251,20 +277,3 @@ impl AvailableBlockSizesConfig {
result
}
}
-
-/// Configuration options related to FeeTicker.
-#[derive(Debug)]
-pub struct FeeTickerOptions {
- pub not_subsidized_tokens: Vec,
-}
-
-impl FeeTickerOptions {
- pub fn from_env() -> Self {
- Self {
- not_subsidized_tokens: get_env("NOT_SUBSIDIZED_TOKENS")
- .split(',')
- .map(|p| p.parse().unwrap())
- .collect(),
- }
- }
-}
diff --git a/etc/env/dev.env.example b/etc/env/dev.env.example
index 7cefefc08a..2c5da5138d 100755
--- a/etc/env/dev.env.example
+++ b/etc/env/dev.env.example
@@ -180,3 +180,7 @@ FEE_ACCOUNT_PRIVATE_KEY=unset
# Set of token addresses for which no subsidies are provided.
NOT_SUBSIDIZED_TOKENS=2b591e99afe9f32eaa6214f7b7629768c40eeb39,34083bbd70d394110487feaa087da875a54624ec
+
+# Set of token addresses which are not acceptable in the ticker for paying fees in.
+# Should be a comma-separated list.
+TICKER_DISABLED_TOKENS=38A2fDc11f526Ddd5a607C1F251C065f40fBF2f7