Skip to content

Commit d0c9d33

Browse files
committed
migrate from ethabi to alloy
1 parent 0f5f778 commit d0c9d33

File tree

32 files changed

+2550
-417
lines changed

32 files changed

+2550
-417
lines changed

Cargo.lock

Lines changed: 1429 additions & 91 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ repository = "https://github.com/graphprotocol/graph-node"
3939
license = "MIT OR Apache-2.0"
4040

4141
[workspace.dependencies]
42+
alloy = { version = "0.11.1", features = ["dyn-abi", "json-abi"] }
4243
anyhow = "1.0"
4344
async-graphql = { version = "7.0.15", features = ["chrono"] }
4445
async-graphql-axum = "7.0.15"

chain/ethereum/src/adapter.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use anyhow::Error;
2-
use ethabi::{Error as ABIError, ParamType, Token};
2+
use graph::abi;
33
use graph::blockchain::ChainIdentifier;
44
use graph::components::subgraph::MappingError;
55
use graph::data::store::ethereum::call;
@@ -101,13 +101,12 @@ pub enum EthereumRpcError {
101101

102102
#[derive(Error, Debug)]
103103
pub enum ContractCallError {
104-
#[error("ABI error: {0}")]
105-
ABIError(#[from] ABIError),
106-
/// `Token` is not of expected `ParamType`
107-
#[error("type mismatch, token {0:?} is not of kind {1:?}")]
108-
TypeError(Token, ParamType),
109-
#[error("error encoding input call data: {0}")]
110-
EncodingError(ethabi::Error),
104+
#[error("ABI error: {0:#}")]
105+
ABIError(anyhow::Error),
106+
#[error("type mismatch, decoded value {0:?} is not of kind {1:?}")]
107+
TypeError(abi::DynSolValue, abi::DynSolType),
108+
#[error("error encoding input call data: {0:#}")]
109+
EncodingError(anyhow::Error),
111110
#[error("call error: {0}")]
112111
Web3Error(web3::Error),
113112
#[error("ethereum node took too long to perform call")]
@@ -1157,7 +1156,7 @@ pub trait EthereumAdapter: Send + Sync + 'static {
11571156
logger: &Logger,
11581157
call: &ContractCall,
11591158
cache: Arc<dyn EthereumCallCache>,
1160-
) -> Result<(Option<Vec<Token>>, call::Source), ContractCallError>;
1159+
) -> Result<(Option<Vec<abi::DynSolValue>>, call::Source), ContractCallError>;
11611160

11621161
/// Make multiple contract calls in a single batch. The returned `Vec`
11631162
/// has results in the same order as the calls in `calls` on input. The
@@ -1167,7 +1166,7 @@ pub trait EthereumAdapter: Send + Sync + 'static {
11671166
logger: &Logger,
11681167
calls: &[&ContractCall],
11691168
cache: Arc<dyn EthereumCallCache>,
1170-
) -> Result<Vec<(Option<Vec<Token>>, call::Source)>, ContractCallError>;
1169+
) -> Result<Vec<(Option<Vec<abi::DynSolValue>>, call::Source)>, ContractCallError>;
11711170

11721171
async fn get_balance(
11731172
&self,
@@ -1196,9 +1195,9 @@ mod tests {
11961195
use graph::blockchain::TriggerFilter as _;
11971196
use graph::firehose::{CallToFilter, CombinedFilter, LogFilter, MultiLogFilter};
11981197
use graph::petgraph::graphmap::GraphMap;
1199-
use graph::prelude::ethabi::ethereum_types::H256;
12001198
use graph::prelude::web3::types::Address;
12011199
use graph::prelude::web3::types::Bytes;
1200+
use graph::prelude::web3::types::H256;
12021201
use graph::prelude::EthereumCall;
12031202
use hex::ToHex;
12041203
use itertools::Itertools;

chain/ethereum/src/data_source.rs

Lines changed: 31 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use anyhow::{anyhow, Error};
22
use anyhow::{ensure, Context};
3+
use graph::abi;
4+
use graph::abi::EventExt;
5+
use graph::abi::FunctionExt;
36
use graph::blockchain::{BlockPtr, TriggerWithHandler};
47
use graph::components::metrics::subgraph::SubgraphInstanceMetrics;
58
use graph::components::store::{EthereumCallCache, StoredDynamicDataSource};
@@ -13,8 +16,8 @@ use graph::env::ENV_VARS;
1316
use graph::futures03::future::try_join;
1417
use graph::futures03::stream::FuturesOrdered;
1518
use graph::futures03::TryStreamExt;
16-
use graph::prelude::ethabi::ethereum_types::H160;
17-
use graph::prelude::ethabi::StateMutability;
19+
use graph::prelude::web3::types::Address;
20+
use graph::prelude::web3::types::H160;
1821
use graph::prelude::{Link, SubgraphManifestValidationError};
1922
use graph::slog::{debug, error, o, trace};
2023
use itertools::Itertools;
@@ -30,9 +33,7 @@ use tiny_keccak::{keccak256, Keccak};
3033
use graph::{
3134
blockchain::{self, Blockchain},
3235
prelude::{
33-
async_trait,
34-
ethabi::{Address, Event, Function, LogParam, ParamType, RawLog},
35-
serde_json, warn,
36+
async_trait, serde_json, warn,
3637
web3::types::{Log, Transaction, H256},
3738
BlockNumber, CheapClone, EthereumCall, LightEthereumBlock, LightEthereumBlockExt,
3839
LinkResolver, Logger,
@@ -525,28 +526,28 @@ impl DataSource {
525526
}
526527
}
527528

528-
/// Returns the contract event with the given signature, if it exists. A an event from the ABI
529+
/// Returns the contract event with the given signature, if it exists. An event from the ABI
529530
/// will be matched if:
530531
/// 1. An event signature is equal to `signature`.
531532
/// 2. There are no equal matches, but there is exactly one event that equals `signature` if all
532533
/// `indexed` modifiers are removed from the parameters.
533-
fn contract_event_with_signature(&self, signature: &str) -> Option<&Event> {
534+
fn contract_event_with_signature(&self, signature: &str) -> Option<&abi::Event> {
534535
// Returns an `Event(uint256,address)` signature for an event, without `indexed` hints.
535-
fn ambiguous_event_signature(event: &Event) -> String {
536+
fn ambiguous_event_signature(event: &abi::Event) -> String {
536537
format!(
537538
"{}({})",
538539
event.name,
539540
event
540541
.inputs
541542
.iter()
542-
.map(|input| event_param_type_signature(&input.kind))
543+
.map(|input| input.selector_type().into_owned())
543544
.collect::<Vec<_>>()
544545
.join(",")
545546
)
546547
}
547548

548549
// Returns an `Event(indexed uint256,address)` type signature for an event.
549-
fn event_signature(event: &Event) -> String {
550+
fn event_signature(event: &abi::Event) -> String {
550551
format!(
551552
"{}({})",
552553
event.name,
@@ -556,40 +557,13 @@ impl DataSource {
556557
.map(|input| format!(
557558
"{}{}",
558559
if input.indexed { "indexed " } else { "" },
559-
event_param_type_signature(&input.kind)
560+
input.selector_type()
560561
))
561562
.collect::<Vec<_>>()
562563
.join(",")
563564
)
564565
}
565566

566-
// Returns the signature of an event parameter type (e.g. `uint256`).
567-
fn event_param_type_signature(kind: &ParamType) -> String {
568-
use ParamType::*;
569-
570-
match kind {
571-
Address => "address".into(),
572-
Bytes => "bytes".into(),
573-
Int(size) => format!("int{}", size),
574-
Uint(size) => format!("uint{}", size),
575-
Bool => "bool".into(),
576-
String => "string".into(),
577-
Array(inner) => format!("{}[]", event_param_type_signature(inner)),
578-
FixedBytes(size) => format!("bytes{}", size),
579-
FixedArray(inner, size) => {
580-
format!("{}[{}]", event_param_type_signature(inner), size)
581-
}
582-
Tuple(components) => format!(
583-
"({})",
584-
components
585-
.iter()
586-
.map(event_param_type_signature)
587-
.collect::<Vec<_>>()
588-
.join(",")
589-
),
590-
}
591-
}
592-
593567
self.contract_abi
594568
.contract
595569
.events()
@@ -628,7 +602,9 @@ impl DataSource {
628602
})
629603
}
630604

631-
fn contract_function_with_signature(&self, target_signature: &str) -> Option<&Function> {
605+
fn contract_function_with_signature(&self, target_signature: &str) -> Option<&abi::Function> {
606+
use abi::StateMutability;
607+
632608
self.contract_abi
633609
.contract
634610
.functions()
@@ -642,7 +618,7 @@ impl DataSource {
642618
let mut arguments = function
643619
.inputs
644620
.iter()
645-
.map(|input| format!("{}", input.kind))
621+
.map(|input| input.selector_type().into_owned())
646622
.collect::<Vec<String>>()
647623
.join(",");
648624
// `address,uint256,bool)
@@ -732,11 +708,7 @@ impl DataSource {
732708
.into_iter()
733709
.filter_map(|(event_handler, event_abi)| {
734710
event_abi
735-
.parse_log(RawLog {
736-
topics: log.topics.clone(),
737-
data: log.data.clone().0,
738-
})
739-
.map(|log| log.params)
711+
.decode_log(&log)
740712
.map_err(|e| {
741713
trace!(
742714
logger,
@@ -841,20 +813,15 @@ impl DataSource {
841813
)
842814
})?;
843815

844-
// Parse the inputs
845-
//
846-
// Take the input for the call, chop off the first 4 bytes, then call
847-
// `function.decode_input` to get a vector of `Token`s. Match the `Token`s
848-
// with the `Param`s in `function.inputs` to create a `Vec<LogParam>`.
849-
let tokens = match function_abi.decode_input(&call.input.0[4..]).with_context(
850-
|| {
816+
let values = match function_abi
817+
.abi_decode_input(&call.input.0[4..])
818+
.with_context(|| {
851819
format!(
852820
"Generating function inputs for the call {:?} failed, raw input: {}",
853821
&function_abi,
854822
hex::encode(&call.input.0)
855823
)
856-
},
857-
) {
824+
}) {
858825
Ok(val) => val,
859826
// See also 280b0108-a96e-4738-bb37-60ce11eeb5bf
860827
Err(err) => {
@@ -864,27 +831,22 @@ impl DataSource {
864831
};
865832

866833
ensure!(
867-
tokens.len() == function_abi.inputs.len(),
834+
values.len() == function_abi.inputs.len(),
868835
"Number of arguments in call does not match \
869836
number of inputs in function signature."
870837
);
871838

872-
let inputs = tokens
839+
let inputs = values
873840
.into_iter()
874841
.enumerate()
875-
.map(|(i, token)| LogParam {
842+
.map(|(i, value)| abi::DynSolParam {
876843
name: function_abi.inputs[i].name.clone(),
877-
value: token,
844+
value,
878845
})
879846
.collect::<Vec<_>>();
880847

881-
// Parse the outputs
882-
//
883-
// Take the output for the call, then call `function.decode_output` to
884-
// get a vector of `Token`s. Match the `Token`s with the `Param`s in
885-
// `function.outputs` to create a `Vec<LogParam>`.
886-
let tokens = function_abi
887-
.decode_output(&call.output.0)
848+
let values = function_abi
849+
.abi_decode_output(&call.output.0)
888850
.with_context(|| {
889851
format!(
890852
"Decoding function outputs for the call {:?} failed, raw output: {}",
@@ -894,17 +856,17 @@ impl DataSource {
894856
})?;
895857

896858
ensure!(
897-
tokens.len() == function_abi.outputs.len(),
859+
values.len() == function_abi.outputs.len(),
898860
"Number of parameters in the call output does not match \
899861
number of outputs in the function signature."
900862
);
901863

902-
let outputs = tokens
864+
let outputs = values
903865
.into_iter()
904866
.enumerate()
905-
.map(|(i, token)| LogParam {
867+
.map(|(i, value)| abi::DynSolParam {
906868
name: function_abi.outputs[i].name.clone(),
907-
value: token,
869+
value,
908870
})
909871
.collect::<Vec<_>>();
910872

0 commit comments

Comments
 (0)