Skip to content

Commit 2e97467

Browse files
committed
chain/ethereum: Migrate eth_call to use alloy
1 parent 28c39c2 commit 2e97467

File tree

4 files changed

+41
-43
lines changed

4 files changed

+41
-43
lines changed

chain/ethereum/src/adapter.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ pub enum ContractCallError {
112112
EncodingError(anyhow::Error),
113113
#[error("call error: {0}")]
114114
Web3Error(web3::Error),
115+
#[error("call error: {0}")]
116+
AlloyError(RpcError<TransportErrorKind>),
115117
#[error("ethereum node took too long to perform call")]
116118
Timeout,
117119
#[error("internal error: {0}")]

chain/ethereum/src/call_helper.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use crate::{ContractCallError, ENV_VARS};
22
use graph::{
33
abi,
44
data::store::ethereum::call,
5-
prelude::{web3, Logger},
5+
prelude::{
6+
alloy::transports::{RpcError, TransportErrorKind},
7+
Logger,
8+
},
69
slog::info,
710
};
811

@@ -79,33 +82,33 @@ fn as_solidity_revert_reason(bytes: &[u8]) -> Option<String> {
7982
/// EVM reverts. Returns `Ok(Null)` for reverts or a proper error otherwise.
8083
pub fn interpret_eth_call_error(
8184
logger: &Logger,
82-
err: web3::Error,
85+
err: RpcError<TransportErrorKind>,
8386
) -> Result<call::Retval, ContractCallError> {
8487
fn reverted(logger: &Logger, reason: &str) -> Result<call::Retval, ContractCallError> {
8588
info!(logger, "Contract call reverted"; "reason" => reason);
8689
Ok(call::Retval::Null)
8790
}
8891

89-
if let web3::Error::Rpc(rpc_error) = &err {
92+
if let RpcError::ErrorResp(rpc_error) = &err {
9093
if is_geth_revert_message(&rpc_error.message) {
9194
return reverted(logger, &rpc_error.message);
9295
}
9396
}
9497

95-
if let web3::Error::Rpc(rpc_error) = &err {
96-
let code = rpc_error.code.code();
97-
let data = rpc_error.data.as_ref().and_then(|d| d.as_str());
98+
if let RpcError::ErrorResp(rpc_error) = &err {
99+
let code = rpc_error.code;
100+
let data = rpc_error.data.as_ref().map(|d| d.to_string());
98101

99102
if code == PARITY_VM_EXECUTION_ERROR {
100103
if let Some(data) = data {
101-
if is_parity_revert(data) {
102-
return reverted(logger, &parity_revert_reason(data));
104+
if is_parity_revert(&data) {
105+
return reverted(logger, &parity_revert_reason(&data));
103106
}
104107
}
105108
}
106109
}
107110

108-
Err(ContractCallError::Web3Error(err))
111+
Err(ContractCallError::AlloyError(err))
109112
}
110113

111114
fn is_parity_revert(data: &str) -> bool {

chain/ethereum/src/ethereum_adapter.rs

Lines changed: 21 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use graph::futures03::{
2020
self, compat::Future01CompatExt, FutureExt, StreamExt, TryFutureExt, TryStreamExt,
2121
};
2222
use graph::prelude::alloy;
23+
use graph::prelude::alloy::rpc::types::{TransactionInput, TransactionRequest};
2324
use graph::prelude::tokio::try_join;
2425
use graph::slog::o;
2526
use graph::tokio::sync::RwLock;
@@ -31,10 +32,7 @@ use graph::{
3132
async_trait, debug, error, hex, info, retry, serde_json as json, trace, warn,
3233
web3::{
3334
self,
34-
types::{
35-
BlockId, Bytes, CallRequest, Filter, FilterBuilder, Log, Transaction,
36-
TransactionReceipt, H256,
37-
},
35+
types::{BlockId, Filter, FilterBuilder, Log, Transaction, TransactionReceipt, H256},
3836
},
3937
BlockNumber, ChainStore, CheapClone, DynTryFuture, Error, EthereumCallCache, Logger,
4038
TimeoutError,
@@ -514,18 +512,7 @@ impl EthereumAdapter {
514512
.boxed()
515513
}
516514

517-
// Method to determine block_id based on support for EIP-1898
518-
fn block_ptr_to_id(&self, block_ptr: &BlockPtr) -> BlockId {
519-
// Ganache does not support calls by block hash.
520-
// See https://github.com/trufflesuite/ganache-cli/issues/973
521-
if !self.supports_eip_1898 {
522-
BlockId::Number(block_ptr.number.into())
523-
} else {
524-
BlockId::Hash(block_ptr.hash_as_h256())
525-
}
526-
}
527-
528-
fn block_ptr_to_alloy_block_id(&self, block_ptr: &BlockPtr) -> alloy::rpc::types::BlockId {
515+
fn block_ptr_to_id(&self, block_ptr: &BlockPtr) -> alloy::rpc::types::BlockId {
529516
if !self.supports_eip_1898 {
530517
alloy::rpc::types::BlockId::number(block_ptr.number as u64)
531518
} else {
@@ -544,7 +531,7 @@ impl EthereumAdapter {
544531
let alloy = self.alloy.clone();
545532
let logger = Logger::new(&logger, o!("provider" => self.provider.clone()));
546533

547-
let block_id = self.block_ptr_to_alloy_block_id(&block_ptr);
534+
let block_id = self.block_ptr_to_id(&block_ptr);
548535
let retry_log_message = format!("eth_getCode RPC call for block {}", block_ptr);
549536

550537
retry(retry_log_message, &logger)
@@ -578,7 +565,7 @@ impl EthereumAdapter {
578565
let alloy = self.alloy.clone();
579566
let logger = Logger::new(&logger, o!("provider" => self.provider.clone()));
580567

581-
let block_id = self.block_ptr_to_alloy_block_id(&block_ptr);
568+
let block_id = self.block_ptr_to_id(&block_ptr);
582569
let retry_log_message = format!("eth_getBalance RPC call for block {}", block_ptr);
583570

584571
retry(retry_log_message, &logger)
@@ -610,33 +597,33 @@ impl EthereumAdapter {
610597
block_ptr: BlockPtr,
611598
gas: Option<u32>,
612599
) -> Result<call::Retval, ContractCallError> {
613-
let web3 = self.web3.clone();
600+
let alloy = self.alloy.clone();
614601
let logger = Logger::new(&logger, o!("provider" => self.provider.clone()));
615602

616-
let block_id = self.block_ptr_to_id(&block_ptr);
603+
let alloy_block_id = self.block_ptr_to_id(&block_ptr);
617604
let retry_log_message = format!("eth_call RPC call for block {}", block_ptr);
618605
retry(retry_log_message, &logger)
619606
.redact_log_urls(true)
620607
.limit(ENV_VARS.request_retries)
621608
.timeout_secs(ENV_VARS.json_rpc_timeout.as_secs())
622609
.run(move || {
623610
let call_data = call_data.clone();
624-
let web3 = web3.cheap_clone();
611+
let alloy = alloy.cheap_clone();
625612
let logger = logger.cheap_clone();
626613
async move {
627-
let req = CallRequest {
628-
to: Some(call_data.address),
629-
gas: gas.map(|val| web3::types::U256::from(val)),
630-
data: Some(Bytes::from(call_data.encoded_call.to_vec())),
631-
from: None,
632-
gas_price: None,
633-
value: None,
634-
access_list: None,
635-
max_fee_per_gas: None,
636-
max_priority_fee_per_gas: None,
637-
transaction_type: None,
638-
};
639-
let result = web3.eth().call(req, Some(block_id)).boxed().await;
614+
let mut req = TransactionRequest::default()
615+
.input(TransactionInput::both(alloy::primitives::Bytes::from(
616+
call_data.encoded_call.to_vec(),
617+
)))
618+
.to(alloy::primitives::Address::from(
619+
call_data.address.as_fixed_bytes(),
620+
));
621+
622+
if let Some(gas) = gas {
623+
req = req.gas_limit(gas as u64);
624+
}
625+
626+
let result = alloy.call(req).block(alloy_block_id).await;
640627

641628
match result {
642629
Ok(bytes) => Ok(call::Retval::Value(scalar::Bytes::from(bytes))),

graph/src/data/store/scalar/bytes.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,9 @@ impl FromSql<diesel::sql_types::Binary, diesel::pg::Pg> for Bytes {
123123
<Vec<u8> as FromSql<diesel::sql_types::Binary, _>>::from_sql(value).map(Bytes::from)
124124
}
125125
}
126+
127+
impl From<alloy::primitives::Bytes> for Bytes {
128+
fn from(bytes: alloy::primitives::Bytes) -> Bytes {
129+
Bytes::from(bytes.as_ref())
130+
}
131+
}

0 commit comments

Comments
 (0)