Skip to content

Commit cd549ee

Browse files
committed
Migrate transaction receipt to alloy
1 parent 3b8ae52 commit cd549ee

File tree

7 files changed

+267
-76
lines changed

7 files changed

+267
-76
lines changed

chain/ethereum/src/codec.rs

Lines changed: 61 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -292,66 +292,67 @@ impl TryInto<EthereumBlockWithCalls> for &Block {
292292
.iter()
293293
.filter_map(|t| {
294294
t.receipt.as_ref().map(|r| {
295-
Ok(web3::types::TransactionReceipt {
296-
transaction_hash: t.hash.try_decode_proto("transaction hash")?,
297-
transaction_index: U64::from(t.index),
298-
block_hash: Some(
299-
self.hash.try_decode_proto("transaction block hash")?,
300-
),
301-
block_number: Some(U64::from(self.number)),
302-
cumulative_gas_used: U256::from(r.cumulative_gas_used),
303-
// FIXME (SF): What is the rule here about gas_used being None, when it's 0?
304-
gas_used: Some(U256::from(t.gas_used)),
305-
contract_address: {
306-
match t.calls.len() {
307-
0 => None,
308-
_ => {
309-
match CallType::try_from(t.calls[0].call_type).map_err(
310-
|_| {
311-
graph::anyhow::anyhow!(
312-
"invalid call type: {}",
313-
t.calls[0].call_type,
314-
)
315-
},
316-
)? {
317-
CallType::Create => {
318-
Some(t.calls[0].address.try_decode_proto(
319-
"transaction contract address",
320-
)?)
321-
}
322-
_ => None,
323-
}
324-
}
325-
}
326-
},
327-
logs: r
328-
.logs
329-
.iter()
330-
.map(|l| LogAt::new(l, self, t).try_into())
331-
.collect::<Result<Vec<_>, Error>>()?,
332-
status: TransactionTraceStatus::try_from(t.status)
333-
.map_err(|_| {
334-
graph::anyhow::anyhow!(
335-
"invalid transaction trace status: {}",
336-
t.status
337-
)
338-
})?
339-
.try_into()?,
340-
root: match r.state_root.len() {
341-
0 => None, // FIXME (SF): should this instead map to [0;32]?
342-
// FIXME (SF): if len < 32, what do we do?
343-
_ => Some(
344-
r.state_root.try_decode_proto("transaction state root")?,
345-
),
346-
},
347-
logs_bloom: r
348-
.logs_bloom
349-
.try_decode_proto("transaction logs bloom")?,
350-
from: t.from.try_decode_proto("transaction from")?,
351-
to: get_to_address(t)?,
352-
transaction_type: None,
353-
effective_gas_price: None,
354-
})
295+
// Ok(web3::types::TransactionReceipt {
296+
// transaction_hash: t.hash.try_decode_proto("transaction hash")?,
297+
// transaction_index: U64::from(t.index),
298+
// block_hash: Some(
299+
// self.hash.try_decode_proto("transaction block hash")?,
300+
// ),
301+
// block_number: Some(U64::from(self.number)),
302+
// cumulative_gas_used: U256::from(r.cumulative_gas_used),
303+
// // FIXME (SF): What is the rule here about gas_used being None, when it's 0?
304+
// gas_used: Some(U256::from(t.gas_used)),
305+
// contract_address: {
306+
// match t.calls.len() {
307+
// 0 => None,
308+
// _ => {
309+
// match CallType::try_from(t.calls[0].call_type).map_err(
310+
// |_| {
311+
// graph::anyhow::anyhow!(
312+
// "invalid call type: {}",
313+
// t.calls[0].call_type,
314+
// )
315+
// },
316+
// )? {
317+
// CallType::Create => {
318+
// Some(t.calls[0].address.try_decode_proto(
319+
// "transaction contract address",
320+
// )?)
321+
// }
322+
// _ => None,
323+
// }
324+
// }
325+
// }
326+
// },
327+
// logs: r
328+
// .logs
329+
// .iter()
330+
// .map(|l| LogAt::new(l, self, t).try_into())
331+
// .collect::<Result<Vec<_>, Error>>()?,
332+
// status: TransactionTraceStatus::try_from(t.status)
333+
// .map_err(|_| {
334+
// graph::anyhow::anyhow!(
335+
// "invalid transaction trace status: {}",
336+
// t.status
337+
// )
338+
// })?
339+
// .try_into()?,
340+
// root: match r.state_root.len() {
341+
// 0 => None, // FIXME (SF): should this instead map to [0;32]?
342+
// // FIXME (SF): if len < 32, what do we do?
343+
// _ => Some(
344+
// r.state_root.try_decode_proto("transaction state root")?,
345+
// ),
346+
// },
347+
// logs_bloom: r
348+
// .logs_bloom
349+
// .try_decode_proto("transaction logs bloom")?,
350+
// from: t.from.try_decode_proto("transaction from")?,
351+
// to: get_to_address(t)?,
352+
// transaction_type: None,
353+
// effective_gas_price: None,
354+
// })
355+
Ok(alloy_todo!())
355356
})
356357
})
357358
.collect::<Result<Vec<_>, Error>>()?

chain/ethereum/src/ethereum_adapter.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ use graph::prelude::{
3737
},
3838
transports::{RpcError, TransportErrorKind},
3939
},
40-
alloy_log_to_web3_log, alloy_transaction_receipt_to_web3_transaction_receipt,
41-
h160_to_alloy_address, h256_to_b256,
40+
alloy_log_to_web3_log, h160_to_alloy_address, h256_to_b256,
4241
tokio::try_join,
4342
};
4443
use graph::slog::o;
@@ -1370,7 +1369,7 @@ impl EthereumAdapterTrait for EthereumAdapter {
13701369
block: Arc::new(alloy_block_to_block(block)),
13711370
transaction_receipts: transaction_receipts
13721371
.into_iter()
1373-
.map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt))
1372+
.map(|receipt| receipt)
13741373
.collect(),
13751374
})
13761375
}
@@ -1903,7 +1902,7 @@ pub(crate) fn parse_log_triggers(
19031902
.transaction_receipts
19041903
.iter()
19051904
.flat_map(move |receipt| {
1906-
receipt.logs.iter().enumerate().map(move |(index, _)| {
1905+
receipt.logs().iter().enumerate().map(move |(index, _)| {
19071906
EthereumTrigger::Log(LogRef::LogPosition(index, receipt.cheap_clone()))
19081907
})
19091908
})
@@ -2525,8 +2524,6 @@ async fn get_logs_and_transactions(
25252524
.transaction_hash
25262525
.and_then(|txn| transaction_receipts_by_hash.get(&txn).cloned());
25272526
let web3_log = alloy_log_to_web3_log(log);
2528-
let optional_receipt = optional_receipt
2529-
.map(|receipt| alloy_transaction_receipt_to_web3_transaction_receipt(receipt));
25302527
let value = EthereumTrigger::Log(LogRef::FullLog(Arc::new(web3_log), optional_receipt));
25312528
log_triggers.push(value);
25322529
}

chain/ethereum/src/runtime/abi.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ use super::runtime_adapter::UnresolvedContractCall;
22
use crate::trigger::{
33
EthereumBlockData, EthereumCallData, EthereumEventData, EthereumTransactionData,
44
};
5+
use anyhow::anyhow;
56
use graph::abi;
7+
use graph::prelude::alloy;
8+
use graph::prelude::alloy::network::ReceiptResponse;
9+
use graph::prelude::alloy::primitives::B256;
610
use graph::{
711
prelude::{
812
web3::types::{Log, TransactionReceipt, H256},
@@ -82,6 +86,20 @@ impl ToAscObj<AscTopicArray> for Vec<H256> {
8286
}
8387
}
8488

89+
impl ToAscObj<AscTopicArray> for &[alloy::primitives::B256] {
90+
fn to_asc_obj<H: AscHeap + ?Sized>(
91+
&self,
92+
heap: &mut H,
93+
gas: &GasCounter,
94+
) -> Result<AscTopicArray, HostExportError> {
95+
let topics = self
96+
.iter()
97+
.map(|topic| asc_new(heap, topic, gas))
98+
.collect::<Result<Vec<_>, _>>()?;
99+
Ok(AscTopicArray(Array::new(&topics, heap, gas)?))
100+
}
101+
}
102+
85103
impl AscIndexId for AscTopicArray {
86104
const INDEX_ASC_TYPE_ID: IndexForAscTypeId = IndexForAscTypeId::ArrayH256;
87105
}
@@ -101,6 +119,20 @@ impl AscType for AscLogArray {
101119
}
102120
}
103121

122+
impl ToAscObj<AscLogArray> for &[alloy::rpc::types::Log] {
123+
fn to_asc_obj<H: AscHeap + ?Sized>(
124+
&self,
125+
heap: &mut H,
126+
gas: &GasCounter,
127+
) -> Result<AscLogArray, HostExportError> {
128+
let logs = self
129+
.iter()
130+
.map(|log| asc_new(heap, &log, gas))
131+
.collect::<Result<Vec<_>, _>>()?;
132+
Ok(AscLogArray(Array::new(&logs, heap, gas)?))
133+
}
134+
}
135+
104136
impl ToAscObj<AscLogArray> for Vec<Log> {
105137
fn to_asc_obj<H: AscHeap + ?Sized>(
106138
&self,
@@ -627,6 +659,50 @@ where
627659
}
628660
}
629661

662+
impl<'a, T, B> ToAscObj<AscEthereumEvent_0_0_7<T, B>>
663+
for (
664+
EthereumEventData<'a>,
665+
Option<&alloy::rpc::types::TransactionReceipt>,
666+
)
667+
where
668+
T: AscType + AscIndexId,
669+
B: AscType + AscIndexId,
670+
EthereumTransactionData<'a>: ToAscObj<T>,
671+
EthereumBlockData<'a>: ToAscObj<B>,
672+
{
673+
fn to_asc_obj<H: AscHeap + ?Sized>(
674+
&self,
675+
heap: &mut H,
676+
gas: &GasCounter,
677+
) -> Result<AscEthereumEvent_0_0_7<T, B>, HostExportError> {
678+
let (event_data, optional_receipt) = self;
679+
let AscEthereumEvent {
680+
address,
681+
log_index,
682+
transaction_log_index,
683+
log_type,
684+
block,
685+
transaction,
686+
params,
687+
} = event_data.to_asc_obj(heap, gas)?;
688+
let receipt = if let Some(receipt_data) = optional_receipt {
689+
asc_new(heap, receipt_data, gas)?
690+
} else {
691+
AscPtr::null()
692+
};
693+
Ok(AscEthereumEvent_0_0_7 {
694+
address,
695+
log_index,
696+
transaction_log_index,
697+
log_type,
698+
block,
699+
transaction,
700+
params,
701+
receipt,
702+
})
703+
}
704+
}
705+
630706
impl ToAscObj<AscEthereumLog> for Log {
631707
fn to_asc_obj<H: AscHeap + ?Sized>(
632708
&self,
@@ -674,6 +750,92 @@ impl ToAscObj<AscEthereumLog> for Log {
674750
}
675751
}
676752

753+
impl ToAscObj<AscEthereumLog> for alloy::rpc::types::Log {
754+
fn to_asc_obj<H: AscHeap + ?Sized>(
755+
&self,
756+
heap: &mut H,
757+
gas: &GasCounter,
758+
) -> Result<AscEthereumLog, HostExportError> {
759+
Ok(AscEthereumLog {
760+
address: asc_new(heap, &self.address(), gas)?,
761+
topics: asc_new(heap, &self.topics(), gas)?,
762+
data: asc_new(heap, self.data().data.as_ref(), gas)?,
763+
block_hash: self
764+
.block_hash
765+
.map(|block_hash| asc_new(heap, &block_hash, gas))
766+
.unwrap_or(Ok(AscPtr::null()))?,
767+
block_number: self
768+
.block_number
769+
.map(|block_number| asc_new(heap, &BigInt::from(block_number), gas))
770+
.unwrap_or(Ok(AscPtr::null()))?,
771+
transaction_hash: self
772+
.transaction_hash
773+
.map(|txn_hash| asc_new(heap, &txn_hash, gas))
774+
.unwrap_or(Ok(AscPtr::null()))?,
775+
transaction_index: self
776+
.transaction_index
777+
.map(|txn_index| asc_new(heap, &BigInt::from(txn_index), gas))
778+
.unwrap_or(Ok(AscPtr::null()))?,
779+
log_index: self
780+
.log_index
781+
.map(|log_index| asc_new(heap, &BigInt::from(log_index), gas))
782+
.unwrap_or(Ok(AscPtr::null()))?,
783+
transaction_log_index: AscPtr::null(), // TODO(alloy): figure out how to get transaction log index
784+
log_type: AscPtr::null(), // TODO(alloy): figure out how to get log type
785+
removed: asc_new(
786+
heap,
787+
&AscWrapped {
788+
inner: self.removed,
789+
},
790+
gas,
791+
)?,
792+
})
793+
}
794+
}
795+
796+
impl ToAscObj<AscEthereumTransactionReceipt> for &alloy::rpc::types::TransactionReceipt {
797+
fn to_asc_obj<H: AscHeap + ?Sized>(
798+
&self,
799+
heap: &mut H,
800+
gas: &GasCounter,
801+
) -> Result<AscEthereumTransactionReceipt, HostExportError> {
802+
Ok(AscEthereumTransactionReceipt {
803+
transaction_hash: asc_new(heap, &self.transaction_hash, gas)?,
804+
transaction_index: asc_new(
805+
heap,
806+
&BigInt::from(
807+
self.transaction_index
808+
.ok_or(HostExportError::Unknown(anyhow!(
809+
"Transaction index is missing"
810+
)))?,
811+
),
812+
gas,
813+
)?,
814+
block_hash: self
815+
.block_hash
816+
.map(|block_hash| asc_new(heap, &block_hash, gas))
817+
.unwrap_or(Ok(AscPtr::null()))?,
818+
block_number: self
819+
.block_number
820+
.map(|block_number| asc_new(heap, &BigInt::from(block_number), gas))
821+
.unwrap_or(Ok(AscPtr::null()))?,
822+
cumulative_gas_used: asc_new(heap, &BigInt::from(self.gas_used), gas)?,
823+
gas_used: asc_new(heap, &BigInt::from(self.gas_used), gas)?,
824+
contract_address: self
825+
.contract_address
826+
.map(|contract_address| asc_new(heap, &contract_address, gas))
827+
.unwrap_or(Ok(AscPtr::null()))?,
828+
logs: asc_new(heap, &self.logs(), gas)?,
829+
status: asc_new(heap, &BigInt::from(self.status() as u64), gas)?,
830+
root: self
831+
.state_root()
832+
.map(|root| asc_new(heap, &root, gas))
833+
.unwrap_or(Ok(AscPtr::null()))?,
834+
logs_bloom: asc_new(heap, self.inner.logs_bloom().as_slice(), gas)?,
835+
})
836+
}
837+
}
838+
677839
impl ToAscObj<AscEthereumTransactionReceipt> for &TransactionReceipt {
678840
fn to_asc_obj<H: AscHeap + ?Sized>(
679841
&self,

0 commit comments

Comments
 (0)