Skip to content

Commit

Permalink
update call_ccip_solidity_method and rename types and functions
Browse files Browse the repository at this point in the history
  • Loading branch information
sevenzing committed Oct 29, 2024
1 parent 4c270d2 commit 0bfbfcb
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 55 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "alloy-ccip-read"
version = "0.2.0"
version = "0.3.0"
authors = ["Lev Lymarenko its@llev.me"]
license = "MIT"
edition = "2018"
Expand Down Expand Up @@ -38,6 +38,7 @@ alloy = { version = "0.5.4", features = ["full", "json-rpc"] }
futures-util = "0.3.29"
anyhow = "1.0.75"
tracing-subscriber = "0.3.18"
derive-new = "0.7.0"

[target.'cfg(target_arch = "wasm32")'.dependencies]
getrandom = { version = "0.2", features = ["js"] }
Expand Down
25 changes: 9 additions & 16 deletions src/protocols/d3.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use super::ens;
use crate::{
contracts, CCIPReader, CCIPReaderError, CCIPType, DomainIdProvider, ResolveResult,
ReverseResolveResult,
contracts, CCIPReader, CCIPReaderError, DomainIdProvider, ResolveResult, ReverseResolveResult,
};
use alloy::{primitives::Address, providers::Provider};

Expand All @@ -24,13 +23,10 @@ pub async fn resolve_d3_name<P: Provider, D: DomainIdProvider>(
network: network.into(),
};
let mut ccip_read_used = false;
let (result, requests) =
ens::query_resolver_non_wildcarded(reader, resolver_address, call).await?;
ccip_read_used |= !requests.is_empty();
let addr = CCIPType {
value: result._0,
requests,
};
let addr = ens::query_resolver_non_wildcarded(reader, resolver_address, call)
.await?
.map(|addr| addr._0);
ccip_read_used |= addr.ccip_read_used();
Ok(ResolveResult {
addr,
ccip_read_used,
Expand All @@ -57,13 +53,10 @@ pub async fn reverse_resolve_d3_name<P: Provider, D: DomainIdProvider>(
network: network.into(),
};
let mut ccip_read_used = false;
let (result, requests) =
ens::query_resolver_non_wildcarded(reader, resolver_address, call).await?;
ccip_read_used |= !requests.is_empty();
let name = CCIPType {
value: result._0,
requests,
};
let name = ens::query_resolver_non_wildcarded(reader, resolver_address, call)
.await?
.map(|name| name._0);
ccip_read_used |= name.ccip_read_used();
Ok(ReverseResolveResult {
name,
ccip_read_used,
Expand Down
40 changes: 16 additions & 24 deletions src/protocols/ens.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use crate::{
consts, contracts,
utils::{dns_encode, iter_parent_names},
CCIPReader, CCIPReaderError, CCIPRequest, CCIPType, DomainIdProvider, ResolveResult,
CCIPReader, CCIPReaderError, CCIPResult, DomainIdProvider, ResolveResult,
};
use alloy::{
network::TransactionBuilder,
primitives::{Address, Bytes},
providers::Provider,
rpc::types::TransactionRequest,
sol_types::{SolCall, SolValue},
transports::BoxTransport,
};
Expand Down Expand Up @@ -117,13 +115,10 @@ pub async fn resolve_name_with_resolver<P: Provider, D: DomainIdProvider>(
let node = reader.domain_id_provider().generate(name);
let addr_call = contracts::IAddrResolver::addrCall { node };
let mut ccip_read_used = false;
let (response, requests) =
query_resolver(reader, name, resolver_address, addr_call, supports_wildcard).await?;
ccip_read_used |= !requests.is_empty();
let addr = CCIPType {
value: response._0,
requests,
};
let addr = query_resolver(reader, name, resolver_address, addr_call, supports_wildcard)
.await?
.map(|addr| addr._0);
ccip_read_used |= !addr.requests.is_empty();
Ok(ResolveResult {
addr,
ccip_read_used,
Expand Down Expand Up @@ -153,7 +148,7 @@ pub async fn query_resolver<P: Provider, D: DomainIdProvider, C: SolCall>(
resolver_address: Address,
call: C,
supports_wildcard: bool,
) -> Result<(<C as SolCall>::Return, Vec<CCIPRequest>), CCIPReaderError> {
) -> Result<CCIPResult<<C as SolCall>::Return>, CCIPReaderError> {
if supports_wildcard {
query_resolver_wildcarded(reader, name, resolver_address, call).await
} else {
Expand Down Expand Up @@ -181,7 +176,7 @@ pub async fn query_resolver_wildcarded<P: Provider, D: DomainIdProvider, C: SolC
name: &str,
resolver_address: Address,
call: C,
) -> Result<(<C as SolCall>::Return, Vec<CCIPRequest>), CCIPReaderError> {
) -> Result<CCIPResult<<C as SolCall>::Return>, CCIPReaderError> {
let dns_encode_name =
dns_encode(name).map_err(|e| CCIPReaderError::InvalidDomain(e.to_string()))?;
let data = call.abi_encode();
Expand All @@ -190,15 +185,15 @@ pub async fn query_resolver_wildcarded<P: Provider, D: DomainIdProvider, C: SolC
.resolve(dns_encode_name.into(), data.into())
.into_transaction_request();

let (mut bytes, requests) = reader.call_ccip(&tx).await?;
let result = reader.call_ccip(&tx).await?;

tracing::debug!(requests =? requests, "finished call_ccip");
tracing::debug!(requests =? result.requests, "finished call_ccip");

bytes = Bytes::abi_decode(&bytes, true)?;
let bytes = Bytes::abi_decode(&result.value, true)?;

let result = C::abi_decode_returns(&bytes, true)?;
let value = C::abi_decode_returns(&bytes, true)?;

Ok((result, requests))
Ok(CCIPResult::new(value, result.requests))
}

/// Query a resolver for a given ENS name and call without using wildcard resolution
Expand All @@ -216,13 +211,10 @@ pub async fn query_resolver_non_wildcarded<P: Provider, D: DomainIdProvider, C:
reader: &CCIPReader<P, D>,
resolver_address: Address,
call: C,
) -> Result<(<C as SolCall>::Return, Vec<CCIPRequest>), CCIPReaderError> {
let tx = TransactionRequest::default()
.with_to(resolver_address)
.with_call(&call);
let (result, requests) = reader.call_ccip(&tx).await?;
let result = C::abi_decode_returns(&result, true)?;
Ok((result, requests))
) -> Result<CCIPResult<<C as SolCall>::Return>, CCIPReaderError> {
reader
.call_ccip_solidity_method(resolver_address, call)
.await
}

fn registry<P: Provider>(
Expand Down
38 changes: 28 additions & 10 deletions src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@ use crate::{
domain_id::DomainIdProvider,
errors::CCIPReaderError,
utils::{build_reqwest, sanitaze_error_data_from_rpc},
CCIPRequest, NamehashIdProvider,
CCIPRequest, CCIPResult, NamehashIdProvider,
};
use alloy::{
eips::BlockId,
hex::FromHex,
network::TransactionBuilder,
primitives::Bytes,
primitives::{Address, Bytes},
providers::{ProviderBuilder, RootProvider},
rpc::types::TransactionRequest,
sol_types::{SolError, SolValue},
sol_types::{SolCall, SolError, SolValue},
transports::{BoxTransport, RpcError, TransportErrorKind},
};
use async_recursion::async_recursion;
Expand Down Expand Up @@ -127,21 +127,39 @@ where
P: alloy::providers::Provider,
D: DomainIdProvider + Send + Sync,
{
pub async fn call(&self, tx: &TransactionRequest) -> Result<Bytes, CCIPReaderError> {
self.call_ccip(tx).await.map(|(result, _)| result)
pub async fn call_and_only_result(
&self,
tx: &TransactionRequest,
) -> Result<Bytes, CCIPReaderError> {
self.call_ccip(tx).await.map(|result| result.into_value())
}

/// Perform eth_call with tx, and handle CCIP requests if needed
/// returning both the result of the call and the CCIP requests made during the call
pub async fn call_ccip(
&self,
tx: &TransactionRequest,
) -> Result<(Bytes, Vec<CCIPRequest>), CCIPReaderError> {
) -> Result<CCIPResult<Bytes>, CCIPReaderError> {
let mut requests = Vec::new();
let mut tx = tx.clone();
self._call(&mut tx, 0, &mut requests).await
}

/// Perform eth_call with tx, and handle CCIP requests if needed
/// returning both the result of the call and the CCIP requests made during the call
pub async fn call_ccip_solidity_method<C: SolCall>(
&self,
contract_address: Address,
call: C,
) -> Result<CCIPResult<<C as SolCall>::Return>, CCIPReaderError> {
let tx = TransactionRequest::default()
.with_to(contract_address)
.with_call(&call);
let result = self.call_ccip(&tx).await?;
let value = C::abi_decode_returns(&result.value, true)?;
Ok(CCIPResult::new(value, result.requests))
}

#[tracing::instrument(
skip(self, transaction, requests_buffer),
fields(tx_to =? transaction.to),
Expand All @@ -153,7 +171,7 @@ where
transaction: &mut TransactionRequest,
attempt: u8,
requests_buffer: &mut Vec<CCIPRequest>,
) -> Result<(Bytes, Vec<CCIPRequest>), CCIPReaderError> {
) -> Result<CCIPResult<Bytes>, CCIPReaderError> {
if attempt >= self.max_redirect_attempt {
// may need more info
return Err(CCIPReaderError::MaxRedirection);
Expand All @@ -165,7 +183,7 @@ where
.await;

match response {
Ok(result) => Ok((result, requests_buffer.to_vec())),
Ok(result) => Ok(CCIPResult::new(result, requests_buffer.to_vec())),
Err(err) => {
tracing::debug!("rpc-error: {:?}", err);
self._handle_rpc_error(err, transaction, attempt, requests_buffer)
Expand All @@ -180,7 +198,7 @@ where
transaction: &mut TransactionRequest,
attempt: u8,
requests_buffer: &mut Vec<CCIPRequest>,
) -> Result<(Bytes, Vec<CCIPRequest>), CCIPReaderError> {
) -> Result<CCIPResult<Bytes>, CCIPReaderError> {
let tx_sender = transaction
.to
.as_ref()
Expand Down Expand Up @@ -270,7 +288,7 @@ mod tests {
.with_input(hex!("9061b92300000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000001701310f6f6666636861696e6578616d706c650365746800000000000000000000000000000000000000000000000000000000000000000000000000000000008459d1d43c1c9fb8c1fe76f464ccec6d2c003169598fdfcbcb6bbddf6af9c097a39fa0048c00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000005656d61696c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"))
.with_to(address!("C1735677a60884ABbCF72295E88d47764BeDa282"));

let result = reader.call(&tx).await.unwrap();
let result = reader.call_and_only_result(&tx).await.unwrap();

let data: Bytes = Bytes::abi_decode(&result, true).unwrap();
let record: String = String::abi_decode(&data, true).unwrap();
Expand Down
26 changes: 22 additions & 4 deletions src/types.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
use alloy::primitives::{Address, Bytes};
use derive_new::new;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone)]
pub struct ResolveResult {
pub addr: CCIPType<Address>,
pub addr: CCIPResult<Address>,
pub ccip_read_used: bool,
pub wildcard_used: bool,
}

pub struct ReverseResolveResult {
pub name: CCIPType<String>,
pub name: CCIPResult<String>,
pub ccip_read_used: bool,
}

#[derive(Debug, Clone)]
pub struct CCIPType<T> {
#[derive(Debug, Clone, new)]
pub struct CCIPResult<T> {
pub value: T,
pub requests: Vec<CCIPRequest>,
}

impl<T> CCIPResult<T> {
pub fn into_value(self) -> T {
self.value
}

pub fn ccip_read_used(&self) -> bool {
!self.requests.is_empty()
}

pub fn map<F, U>(self, f: F) -> CCIPResult<U>
where
F: FnOnce(T) -> U,
{
CCIPResult::new(f(self.value), self.requests)
}
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct CCIPRequest {
pub url: String,
Expand Down

0 comments on commit 0bfbfcb

Please sign in to comment.