Skip to content

Commit ffda5ac

Browse files
mattssegakonst
andauthored
chore(cast): improve invalid signature error (#3342)
Co-authored-by: Georgios Konstantopoulos <me@gakonst.com>
1 parent 32b32c6 commit ffda5ac

File tree

3 files changed

+47
-10
lines changed

3 files changed

+47
-10
lines changed

cast/src/errors.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//! Errors for this crate
2+
3+
use foundry_config::Chain;
4+
use std::fmt;
5+
6+
/// An error thrown when resolving a function via signature failed
7+
#[derive(Debug, Clone)]
8+
pub enum FunctionSignatureError {
9+
MissingEtherscan { sig: String },
10+
UnknownChain(Chain),
11+
MissingToAddress,
12+
}
13+
14+
impl fmt::Display for FunctionSignatureError {
15+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16+
match self {
17+
FunctionSignatureError::MissingEtherscan { sig } => {
18+
writeln!(f, "Failed to determine function signature for `{}`", sig)?;
19+
writeln!(f, "To lookup a function signature of a deployed contract by name, a valid ETHERSCAN_API_KEY must be set.")?;
20+
write!(f, "\tOr did you mean:\t {}()", sig)
21+
}
22+
FunctionSignatureError::UnknownChain(chain) => {
23+
write!(
24+
f,
25+
"Resolving via etherscan requires a known chain. Unknown chain: {}",
26+
chain
27+
)
28+
}
29+
FunctionSignatureError::MissingToAddress => f.write_str("Target address must be set"),
30+
}
31+
}
32+
}
33+
34+
impl std::error::Error for FunctionSignatureError {}

cast/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub use tx::TxBuilder;
2727
use tx::{TxBuilderOutput, TxBuilderPeekOutput};
2828

2929
pub mod base;
30+
pub mod errors;
3031
mod rlp_converter;
3132
mod tx;
3233

cast/src/tx.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::errors::FunctionSignatureError;
12
use ethers_core::{
23
abi::Function,
34
types::{
@@ -6,7 +7,7 @@ use ethers_core::{
67
},
78
};
89
use ethers_providers::Middleware;
9-
use eyre::{eyre, Result, WrapErr};
10+
use eyre::{eyre, Result};
1011
use foundry_common::abi::{encode_args, get_func, get_func_etherscan};
1112
use foundry_config::Chain;
1213
use futures::future::join_all;
@@ -172,19 +173,24 @@ impl<'a, M: Middleware> TxBuilder<'a, M> {
172173
let args = resolve_name_args(&args, self.provider).await;
173174

174175
let func = if sig.contains('(') {
176+
// a regular function signature with parentheses
175177
get_func(sig)?
176178
} else if sig.starts_with("0x") {
177179
// if only calldata is provided, returning a dummy function
178180
get_func("x()")?
179181
} else {
180-
let chain =
181-
self.chain.try_into().wrap_err("resolving via etherscan requires a known chain")?;
182+
let chain = self
183+
.chain
184+
.try_into()
185+
.map_err(|_| FunctionSignatureError::UnknownChain(self.chain))?;
182186
get_func_etherscan(
183187
sig,
184-
self.to.ok_or_else(|| eyre::eyre!("to value must be set"))?,
188+
self.to.ok_or(FunctionSignatureError::MissingToAddress)?,
185189
&args,
186190
chain,
187-
self.etherscan_api_key.as_ref().unwrap_or_else(|| panic!(r#"Unable to determine the function signature from `{}`. To find the function signature from the deployed contract via its name instead, a valid ETHERSCAN_API_KEY must be set."#, sig)),
191+
self.etherscan_api_key.as_ref().ok_or_else(|| {
192+
FunctionSignatureError::MissingEtherscan { sig: sig.to_string() }
193+
})?,
188194
)
189195
.await?
190196
};
@@ -263,16 +269,12 @@ async fn resolve_name_args<M: Middleware>(args: &[String], provider: &M) -> Vec<
263269
#[cfg(test)]
264270
mod tests {
265271
use crate::TxBuilder;
266-
272+
use async_trait::async_trait;
267273
use ethers_core::types::{
268274
transaction::eip2718::TypedTransaction, Address, Chain, NameOrAddress, H160, U256,
269275
};
270276
use ethers_providers::{JsonRpcClient, Middleware, ProviderError};
271-
272277
use serde::{de::DeserializeOwned, Serialize};
273-
274-
use async_trait::async_trait;
275-
276278
use std::str::FromStr;
277279

278280
const ADDR_1: &str = "0000000000000000000000000000000000000001";

0 commit comments

Comments
 (0)