From ca72c64a6513dff0c55aaa14c2a5d7d683ab8370 Mon Sep 17 00:00:00 2001 From: Jordan Oroshiba Date: Wed, 30 Oct 2024 05:13:59 -0700 Subject: [PATCH] fix(bridge-withdrawer, cli)!: use decimals from erc20 contract (#1762) ## Summary Updates CLI and bridge withdrawer to read the decimals off the contract when it is an erc20, to get the accurate decimals to utilize during withdrawal. ## Background Previously it was assumed that all erc20 contracts would have 18 decimals this is not guaranteed. #1760 is a similar fix but relies on configuring the withdrawer correctly. This version automatically reads off of the contract instead if it is an erc20. ## Changes - Read decimals off contract if or fallback to native prevision. ## Testing Ran against Flame to ensure it gets decimals correct on 6 decimal contract + CI tests. ## Changelogs Changelogs updated. --------- Co-authored-by: Richard Janis Goldschmidt --- Cargo.lock | 1 + crates/astria-bridge-contracts/CHANGELOG.md | 4 +++ crates/astria-bridge-contracts/Cargo.toml | 1 + crates/astria-bridge-contracts/src/lib.rs | 37 ++++++++++++++++++++- crates/astria-bridge-withdrawer/Cargo.toml | 4 ++- crates/astria-cli/Cargo.toml | 4 ++- 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f4d73e1cf4..aef7fd15f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -510,6 +510,7 @@ dependencies = [ "serde_json", "tendermint", "thiserror", + "tracing", ] [[package]] diff --git a/crates/astria-bridge-contracts/CHANGELOG.md b/crates/astria-bridge-contracts/CHANGELOG.md index 4f22f52904..f0e8d78dc1 100644 --- a/crates/astria-bridge-contracts/CHANGELOG.md +++ b/crates/astria-bridge-contracts/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +- Read the provided contract's `decimals` function, falling back to a hardcoded + value of 18 if the call fails. + [#1762](https://github.com/astriaorg/astria/pull/1762) + ### Added - Initial release. diff --git a/crates/astria-bridge-contracts/Cargo.toml b/crates/astria-bridge-contracts/Cargo.toml index 7276680038..ef6ce29f7f 100644 --- a/crates/astria-bridge-contracts/Cargo.toml +++ b/crates/astria-bridge-contracts/Cargo.toml @@ -17,3 +17,4 @@ serde = { workspace = true } serde_json = { workspace = true } tendermint = { workspace = true } thiserror = { workspace = true } +tracing = { workspace = true, optional = true } diff --git a/crates/astria-bridge-contracts/src/lib.rs b/crates/astria-bridge-contracts/src/lib.rs index ae5691844c..3a32e43a00 100644 --- a/crates/astria-bridge-contracts/src/lib.rs +++ b/crates/astria-bridge-contracts/src/lib.rs @@ -37,6 +37,23 @@ use ethers::{ }; pub use generated::*; +const NON_ERC20_CONTRACT_DECIMALS: u32 = 18u32; + +macro_rules! warn { + ($($tt:tt)*) => { + #[cfg(feature = "tracing")] + { + #![cfg_attr( + feature = "tracing", + expect( + clippy::used_underscore_binding, + reason = "underscore is needed to quiet `unused-variables` warning if `tracing` feature is not set", + ))] + ::tracing::warn!($($tt)*); + } + } +} + #[derive(Debug, thiserror::Error)] #[error(transparent)] pub struct BuildError(BuildErrorKind); @@ -295,7 +312,25 @@ where .await .map_err(BuildError::call_base_chain_asset_precision)?; - let exponent = 18u32 + let contract_decimals = { + let erc_20_contract = astria_bridgeable_erc20::AstriaBridgeableERC20::new( + contract_address, + provider.clone(), + ); + match erc_20_contract.decimals().call().await { + Ok(decimals) => decimals.into(), + Err(_error) => { + warn!( + error = &_error as &dyn std::error::Error, + "failed reading decimals from contract; assuming it is not an ERC20 \ + contract and falling back to `{NON_ERC20_CONTRACT_DECIMALS}`" + ); + NON_ERC20_CONTRACT_DECIMALS + } + } + }; + + let exponent = contract_decimals .checked_sub(base_chain_asset_precision) .ok_or_else(|| BuildError::bad_divisor(base_chain_asset_precision))?; diff --git a/crates/astria-bridge-withdrawer/Cargo.toml b/crates/astria-bridge-withdrawer/Cargo.toml index ade0a71d37..b1abff56cb 100644 --- a/crates/astria-bridge-withdrawer/Cargo.toml +++ b/crates/astria-bridge-withdrawer/Cargo.toml @@ -30,7 +30,9 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal"] } tokio-util = { workspace = true } tonic = { workspace = true } -astria-bridge-contracts = { path = "../astria-bridge-contracts" } +astria-bridge-contracts = { path = "../astria-bridge-contracts", features = [ + "tracing", +] } astria-build-info = { path = "../astria-build-info", features = ["runtime"] } astria-core = { path = "../astria-core", features = [ "serde", diff --git a/crates/astria-cli/Cargo.toml b/crates/astria-cli/Cargo.toml index 3888c1f737..eabf1c69b2 100644 --- a/crates/astria-cli/Cargo.toml +++ b/crates/astria-cli/Cargo.toml @@ -20,7 +20,9 @@ serde_yaml = "0.9.25" termion = "4.0.3" tracing-subscriber = "0.3.18" -astria-bridge-contracts = { path = "../astria-bridge-contracts" } +astria-bridge-contracts = { path = "../astria-bridge-contracts", features = [ + "tracing", +] } astria-core = { path = "../astria-core", features = ["serde"] } clap = { workspace = true, features = ["derive", "env"] }