From 94d6ecdc3877c4a7db085aa655848c46019ed222 Mon Sep 17 00:00:00 2001 From: Fedor Sakharov Date: Tue, 14 Nov 2023 16:34:35 +0100 Subject: [PATCH] fix: correctly determine withdrawal params for withdrawalinitiated events (#301) --- Cargo.lock | 12 ++----- Cargo.toml | 1 - bin/withdrawal-finalizer/Cargo.toml | 2 ++ bin/withdrawal-finalizer/src/config.rs | 46 ++++++++++++++++++++++++++ bin/withdrawal-finalizer/src/main.rs | 1 + client/Cargo.toml | 1 - client/src/error.rs | 8 ++++- client/src/lib.rs | 37 +++++++++++++++------ 8 files changed, 85 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 008c243d..6a9172b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -538,7 +538,6 @@ dependencies = [ "ethers-log-decode", "hex", "lazy_static", - "lru", "pretty_assertions", "serde", "thiserror", @@ -2219,15 +2218,6 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" -[[package]] -name = "lru" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efa59af2ddfad1854ae27d75009d538d0998b4b2fd47083e743ac1a10e46c60" -dependencies = [ - "hashbrown 0.14.0", -] - [[package]] name = "match_cfg" version = "0.1.0" @@ -4935,6 +4925,8 @@ dependencies = [ "ethers", "eyre", "finalizer", + "serde", + "serde_json", "sqlx", "storage", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 7c91adad..44563171 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,6 @@ tokio = "1.34.0" clap = "4.4.8" tracing = "0.1" tracing-subscriber = "0.3" -lru = "0.12.0" sentry = { version = "0", default-features = false } lazy_static = "1.4.0" itertools = "0.11.0" diff --git a/bin/withdrawal-finalizer/Cargo.toml b/bin/withdrawal-finalizer/Cargo.toml index 18017243..7b52d515 100644 --- a/bin/withdrawal-finalizer/Cargo.toml +++ b/bin/withdrawal-finalizer/Cargo.toml @@ -11,6 +11,8 @@ color-eyre = { workspace = true } ethers = { workspace = true, default-features = false, features = ["ws", "rustls"] } tokio = { workspace = true, features = ["full"] } url = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } eyre = { workspace = true } tokio-stream = { workspace = true } envconfig = { workspace = true } diff --git a/bin/withdrawal-finalizer/src/config.rs b/bin/withdrawal-finalizer/src/config.rs index 792da1a3..01e64bfb 100644 --- a/bin/withdrawal-finalizer/src/config.rs +++ b/bin/withdrawal-finalizer/src/config.rs @@ -1,6 +1,9 @@ +use std::str::FromStr; + use envconfig::Envconfig; use ethers::types::Address; use finalizer::{AddrList, TokenList}; +use serde::{Deserialize, Serialize}; use url::Url; /// Withdrawal finalizer configuration. @@ -77,4 +80,47 @@ pub struct Config { #[envconfig(from = "ENABLE_WITHDRAWAL_METERING")] pub enable_withdrawal_metering: Option, + + #[envconfig(from = "CUSTOM_TOKEN_ADDRESS_MAPPINGS")] + pub custom_token_address_mappings: Option, +} + +#[derive(Deserialize, Serialize, Debug, Eq, PartialEq)] +pub struct CustomTokenAddressMapping { + pub l_1_addr: Address, + pub l_2_addr: Address, +} + +impl FromStr for CustomTokenAddressMapping { + type Err = serde_json::Error; + + fn from_str(s: &str) -> std::result::Result { + serde_json::from_str(s) + } +} + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct CustomTokenAddressMappings(pub Vec); + +impl FromStr for CustomTokenAddressMappings { + type Err = serde_json::Error; + + fn from_str(s: &str) -> std::result::Result { + let res: CustomTokenAddressMappings = serde_json::from_str(s)?; + + Ok(res) + } +} + +impl Config { + /// Returns a mapping of tokens (L1, L2) addresses. + pub fn token_mappings(&self) -> Vec<(Address, Address)> { + self.custom_token_address_mappings + .as_ref() + .map(|f| &f.0) + .unwrap_or(&vec![]) + .iter() + .map(|m| (m.l_1_addr, m.l_2_addr)) + .collect() + } } diff --git a/bin/withdrawal-finalizer/src/main.rs b/bin/withdrawal-finalizer/src/main.rs index f89761d1..facc0081 100644 --- a/bin/withdrawal-finalizer/src/main.rs +++ b/bin/withdrawal-finalizer/src/main.rs @@ -153,6 +153,7 @@ async fn main() -> Result<()> { tracing::info!("No sentry url configured"); } + client::add_predefined_token_addrs(config.token_mappings().as_ref()).await; let stop_vise_exporter = run_vise_exporter()?; // Successful reconnections do not reset the reconnection count trackers in the diff --git a/client/Cargo.toml b/client/Cargo.toml index e6aa3231..38489e0f 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -14,7 +14,6 @@ thiserror = { workspace = true } chrono = { workspace = true, features = ["serde"] } serde = { workspace = true } vise = { workspace = true } -lru = { workspace = true } ethers-log-decode = { workspace = true } lazy_static = { workspace = true } tokio = { workspace = true } diff --git a/client/src/error.rs b/client/src/error.rs index 52e7d93d..6846cfc9 100644 --- a/client/src/error.rs +++ b/client/src/error.rs @@ -1,5 +1,8 @@ use ethers::{ - abi::EncodePackedError, contract::ContractError, prelude::Middleware, providers::ProviderError, + abi::{Address, EncodePackedError}, + contract::ContractError, + prelude::Middleware, + providers::ProviderError, types::H256, }; @@ -44,6 +47,9 @@ pub enum Error { #[error("Message not RLP bytes encoded: {0}")] MessageNotRlpBytes(String), + + #[error("L1 address of L2 token {0:?} is not known")] + L2TokenUnknown(Address), } impl From> for Error { diff --git a/client/src/lib.rs b/client/src/lib.rs index 9ae743a8..2d20e2de 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -8,7 +8,7 @@ mod error; mod metrics; -use std::num::NonZeroUsize; +use std::collections::HashMap; use std::sync::Arc; pub use error::{Error, Result}; @@ -28,7 +28,6 @@ use l1bridge::codegen::{FinalizeWithdrawalCall, IL1Bridge}; use l1messenger::codegen::L1MessageSentFilter; use l2standard_token::codegen::{BridgeBurnFilter, L1AddressCall}; use lazy_static::lazy_static; -use lru::LruCache; use tokio::sync::Mutex; use withdrawal_finalizer::codegen::RequestFinalizeWithdrawal; use zksync_contract::codegen::{FinalizeEthWithdrawalCall, IZkSync}; @@ -82,11 +81,22 @@ pub fn is_eth(address: Address) -> bool { enum WithdrawalEvents { BridgeBurn(BridgeBurnFilter), Withdrawal(WithdrawalFilter), + WithdrawalInitiated(WithdrawalInitiatedFilter), } lazy_static! { - static ref TOKEN_ADDRS: Arc>> = - Arc::new(Mutex::new(LruCache::new(NonZeroUsize::new(64).unwrap()))); + static ref TOKEN_ADDRS: Arc>> = + Arc::new(Mutex::new(HashMap::new())); +} + +/// Adds configurable sets of tokens with known deployment addresses +pub async fn add_predefined_token_addrs(addrs: &[(Address, Address)]) { + println!("ADADAD {addrs:?}"); + let mut addr_lock = TOKEN_ADDRS.lock().await; + + for (addr_l1, addr_l2) in addrs { + addr_lock.insert(*addr_l2, *addr_l1); + } } impl WithdrawalParams { @@ -339,6 +349,13 @@ impl ZksyncMiddleware for Provider

{ let withdrawal_event = WithdrawalEvents::decode_log(&raw_log)?; let l2_to_l1_message_hash = match withdrawal_event { + WithdrawalEvents::WithdrawalInitiated(w) => { + let addr_lock = TOKEN_ADDRS.lock().await; + let l_1_token = addr_lock + .get(&w.l_2_token) + .ok_or(Error::L2TokenUnknown(w.l_2_token))?; + get_l1_bridge_burn_message_keccak(w.amount, w.l_1_receiver, *l_1_token)? + } WithdrawalEvents::BridgeBurn(b) => { let mut addr_lock = TOKEN_ADDRS.lock().await; @@ -357,7 +374,7 @@ impl ZksyncMiddleware for Provider

{ let l1_address = Address::decode(self.call(&call, None).await?)?; - addr_lock.put(withdrawal_log.address, l1_address); + addr_lock.insert(withdrawal_log.address, l1_address); l1_address }; @@ -380,7 +397,7 @@ impl ZksyncMiddleware for Provider

{ let l1_receiver = withdrawal_initiated_event.l_1_receiver; - get_l1_bridge_burn_message_keccak(&b, l1_receiver, l1_address)? + get_l1_bridge_burn_message_keccak(b.amount, l1_receiver, l1_address)? } WithdrawalEvents::Withdrawal(w) => get_l1_withdraw_message_keccak(&w)?, }; @@ -562,7 +579,7 @@ where } fn get_l1_bridge_burn_message_keccak( - burn: &BridgeBurnFilter, + amount: U256, l1_receiver: Address, l1_token: Address, ) -> Result { @@ -570,7 +587,7 @@ fn get_l1_bridge_burn_message_keccak( Token::FixedBytes(FinalizeWithdrawalCall::selector().to_vec()), Token::Address(l1_receiver), Token::Address(l1_token), - Token::Bytes(burn.amount.encode()), + Token::Bytes(amount.encode()), ])?; Ok(ethers::utils::keccak256(message).into()) } @@ -605,7 +622,7 @@ mod tests { }; let a = super::get_l1_bridge_burn_message_keccak( - &bridge_burn, + bridge_burn.amount, // withdraws to the same account on L1, so can take this value. bridge_burn.account, dai_l1_addr, @@ -656,7 +673,7 @@ mod tests { }; let a = super::get_l1_bridge_burn_message_keccak( - &bridge_burn, + bridge_burn.amount, "d1ced2fBDFa24daa9920D37237ca2D4d5616a6e2".parse().unwrap(), dai_l1_addr, )