Skip to content

Commit

Permalink
Merge pull request #1205 from matter-labs/popzxc-config-blacklist
Browse files Browse the repository at this point in the history
Load the list of ticker-disabled tokens from the env config
  • Loading branch information
dvush authored Dec 1, 2020
2 parents 5e7ec31 + f312c0d commit e732e6f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 62 deletions.
23 changes: 15 additions & 8 deletions core/bin/zksync_api/src/fee_ticker/fee_token_validator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -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<Address>,
}

impl FeeTokenValidator {
pub(crate) fn new(cache: impl Into<TokenCacheWrapper>) -> Self {
pub(crate) fn new(
cache: impl Into<TokenCacheWrapper>,
disabled_tokens: HashSet<Address>,
) -> Self {
Self {
tokens_cache: cache.into(),
disabled_tokens,
}
}

Expand All @@ -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.
Expand Down Expand Up @@ -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() {
Expand All @@ -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))
Expand Down
24 changes: 10 additions & 14 deletions core/bin/zksync_api/src/fee_ticker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -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,
Expand Down Expand Up @@ -142,7 +142,7 @@ pub struct TickerConfig {
zkp_cost_chunk_usd: Ratio<BigUint>,
gas_cost_tx: GasOperationsCost,
tokens_risk_factors: HashMap<TokenId, Ratio<BigUint>>,
not_subsidized_tokens: Vec<Address>,
not_subsidized_tokens: HashSet<Address>,
}

#[derive(Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -180,28 +180,27 @@ struct FeeTicker<API, INFO> {

#[must_use]
pub fn run_ticker_task(
token_price_source: TokenPriceSource,
not_subsidized_tokens: Vec<Address>,
fast_processing_coeff: f64,
db_pool: ConnectionPool,
tricker_requests: Receiver<TickerRequest>,
) -> 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);

Expand Down Expand Up @@ -309,10 +308,7 @@ impl<API: FeeTickerAPI, INFO: FeeTickerInfo> FeeTicker<API, INFO> {

/// 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(
Expand Down
8 changes: 5 additions & 3 deletions core/bin/zksync_api/src/fee_ticker/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ fn get_test_ticker_config() -> TickerConfig {
.collect(),
not_subsidized_tokens: vec![
Address::from_str("34083bbd70d394110487feaa087da875a54624ec").unwrap(),
],
]
.into_iter()
.collect(),
}
}

Expand Down Expand Up @@ -155,7 +157,7 @@ fn format_with_dot(num: &Ratio<BigUint>, 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(
Expand Down Expand Up @@ -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(
Expand Down
11 changes: 2 additions & 9 deletions core/bin/zksync_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down
65 changes: 37 additions & 28 deletions core/lib/config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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<Address>,
/// Tokens for which subsidies are disabled.
pub not_subsidized_tokens: HashSet<Address>,
}

impl FeeTickerOptions {
fn comma_separated_addresses(name: &str) -> HashSet<Address> {
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,
Expand All @@ -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<H256>,
pub chain_id: u8,
pub gas_price_factor: f64,
Expand All @@ -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,
}
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -251,20 +277,3 @@ impl AvailableBlockSizesConfig {
result
}
}

/// Configuration options related to FeeTicker.
#[derive(Debug)]
pub struct FeeTickerOptions {
pub not_subsidized_tokens: Vec<H160>,
}

impl FeeTickerOptions {
pub fn from_env() -> Self {
Self {
not_subsidized_tokens: get_env("NOT_SUBSIDIZED_TOKENS")
.split(',')
.map(|p| p.parse().unwrap())
.collect(),
}
}
}
4 changes: 4 additions & 0 deletions etc/env/dev.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit e732e6f

Please sign in to comment.