Skip to content

Commit 4c480bd

Browse files
authored
multicall fallback + improvements (#11)
* skip unncessarily verifying erc1271 signature + remove stray dbg * clippy * add schema titles * fix error reporting for erc1271 verification * Add `serde_with` dependency and implement multicall configuration in contract read logic - Updated `Cargo.toml` to include `serde_with` version 3.14.0. - Enhanced `contract_read.rs` to support multicall configuration with detailed execution strategies. - Introduced `MulticallConfig` enum for flexible multicall handling, including enabling/disabling and custom addresses. - Refactored contract reading logic to utilize multicall by default, with fallback to direct calls on failure. - Improved error handling and response mapping for multicall results.
1 parent 6be3247 commit 4c480bd

File tree

7 files changed

+405
-98
lines changed

7 files changed

+405
-98
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aa-core/src/signer.rs

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use alloy::{
44
dyn_abi::TypedData,
55
primitives::{Address, B256, hex, keccak256},
66
sol,
7-
sol_types::{SolCall, SolValue, decode_revert_reason, eip712_domain},
7+
sol_types::{SolCall, SolValue, eip712_domain},
88
};
99
use engine_core::{
1010
chain::Chain,
1111
credentials::SigningCredential,
12-
error::EngineError,
12+
error::{ContractErrorToEngineError, EngineError},
1313
signer::{AccountSigner, EoaSigner, EoaSigningOptions, Erc4337SigningOptions},
1414
};
1515
use serde::Serialize;
@@ -248,7 +248,7 @@ impl<C: Chain + Clone> SmartAccountSigner<C> {
248248
}
249249

250250
/// Verify ERC-1271 signature
251-
async fn verify_erc1271(&self, hash: B256, signature: &str) -> Result<bool, EngineError> {
251+
pub async fn verify_erc1271(&self, hash: B256, signature: &str) -> Result<bool, EngineError> {
252252
let signature_bytes = hex::decode(signature.strip_prefix("0x").unwrap_or(signature))
253253
.map_err(|_| EngineError::ValidationError {
254254
message: "Invalid signature hex".to_string(),
@@ -263,14 +263,11 @@ impl<C: Chain + Clone> SmartAccountSigner<C> {
263263
.await
264264
{
265265
Ok(response) => {
266-
dbg!(response);
267266
let expected_magic = ERC1271Contract::isValidSignatureCall::SELECTOR;
268267
Ok(response.as_slice() == expected_magic)
269268
}
270269
Err(e) => {
271-
let data = e.as_revert_data().unwrap();
272-
dbg!(decode_revert_reason(data.as_ref()));
273-
Ok(false)
270+
Err(e.to_engine_error(self.chain.chain_id(), Some(self.smart_account.address)))
274271
}
275272
}
276273
}
@@ -333,16 +330,16 @@ impl<C: Chain + Clone> SmartAccountSigner<C> {
333330

334331
if is_deployed {
335332
// Verify ERC-1271 signature for deployed accounts
336-
let message_hash = self.hash_message(message, format);
337-
let is_valid = self.verify_erc1271(message_hash, &signature).await?;
338-
339-
if is_valid {
340-
Ok(signature)
341-
} else {
342-
Err(EngineError::ValidationError {
343-
message: "ERC-1271 signature validation failed".to_string(),
344-
})
345-
}
333+
// let message_hash = self.hash_message(message, format);
334+
// let is_valid = self.verify_erc1271(message_hash, &signature).await?;
335+
336+
// if is_valid {
337+
Ok(signature)
338+
// } else {
339+
// Err(EngineError::ValidationError {
340+
// message: "ERC-1271 signature validation failed".to_string(),
341+
// })
342+
// }
346343
} else {
347344
// Create ERC-6492 signature for undeployed accounts
348345
self.create_erc6492_signature(&signature).await
@@ -359,21 +356,21 @@ impl<C: Chain + Clone> SmartAccountSigner<C> {
359356

360357
if is_deployed {
361358
// Verify ERC-1271 signature for deployed accounts
362-
let typed_data_hash =
363-
typed_data
364-
.eip712_signing_hash()
365-
.map_err(|_e| EngineError::ValidationError {
366-
message: "Failed to compute typed data hash".to_string(),
367-
})?;
368-
let is_valid = self.verify_erc1271(typed_data_hash, &signature).await?;
369-
370-
if is_valid {
371-
Ok(signature)
372-
} else {
373-
Err(EngineError::ValidationError {
374-
message: "ERC-1271 signature validation failed".to_string(),
375-
})
376-
}
359+
// let typed_data_hash =
360+
// typed_data
361+
// .eip712_signing_hash()
362+
// .map_err(|_e| EngineError::ValidationError {
363+
// message: "Failed to compute typed data hash".to_string(),
364+
// })?;
365+
// let is_valid = self.verify_erc1271(typed_data_hash, &signature).await?;
366+
367+
// if is_valid {
368+
Ok(signature)
369+
// } else {
370+
// Err(EngineError::ValidationError {
371+
// message: "ERC-1271 signature validation failed".to_string(),
372+
// })
373+
// }
377374
} else {
378375
// Create ERC-6492 signature for undeployed accounts
379376
self.create_erc6492_signature(&signature).await

core/src/defs.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ use schemars::JsonSchema;
22
use serde::{Deserialize, Serialize};
33

44
#[derive(JsonSchema, Serialize, Deserialize, Clone, utoipa::ToSchema)]
5+
#[schema(title = "EVM Address")]
56
/// ### Address
67
/// Used to represent an EVM address. This is a string of length 42 with a `0x` prefix. Non-checksummed addresses are also supported, but will be converted to checksummed.
78
pub struct AddressDef(pub String);
89

910
#[derive(JsonSchema, Serialize, Deserialize, Clone, utoipa::ToSchema)]
11+
#[schema(title = "Bytes")]
1012
/// # Bytes
1113
/// Used to represent "bytes". This is a 0x prefixed hex string.
1214
pub struct BytesDef(pub String);
1315

1416
#[derive(JsonSchema, Serialize, Deserialize, Clone, utoipa::ToSchema)]
17+
#[schema(title = "U256")]
1518
/// # U256
1619
/// Used to represent a 256-bit unsigned integer. Engine can parse these from any valid encoding of the Ethereum "quantity" format.
1720
pub struct U256Def(pub String);

server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ utoipa = { version = "5.4.0", features = [
4040
] }
4141
utoipa-axum = "0.2.0"
4242
utoipa-scalar = { version = "0.3.0", features = ["axum"] }
43+
serde_with = "3.14.0"

server/src/http/dyn_contract.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,7 @@ impl ContractCall {
198198
fn extract_function_name(&self, method: &str) -> Result<String, EngineError> {
199199
let trimmed = method.trim();
200200

201-
if trimmed.starts_with("function ") {
202-
let after_function = &trimmed[9..];
201+
if let Some(after_function) = trimmed.strip_prefix("function ") {
203202
if let Some(paren_pos) = after_function.find('(') {
204203
return Ok(after_function[..paren_pos].trim().to_string());
205204
}

0 commit comments

Comments
 (0)