Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: impl TryFrom<TransactionReceipt> for ReceiptEnvelope #395

Closed
wants to merge 4 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 89 additions & 2 deletions crates/rpc-types/src/eth/transaction/receipt.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{other::OtherFields, Log};
use alloy_primitives::{Address, Bloom, B256, U128, U256, U64, U8};
use crate::{other::OtherFields, ConversionError, Log};
use alloy_consensus::{Receipt, ReceiptEnvelope, ReceiptWithBloom, TxType};
use alloy_primitives::{Address, Bloom, Log as PrimitivesLog, LogData, B256, U128, U256, U64, U8};
use serde::{Deserialize, Serialize};

/// Transaction receipt
Expand Down Expand Up @@ -69,4 +70,90 @@ impl TransactionReceipt {
}
Some(self.from.create(nonce))
}

/// Returns `true` if the transaction was successful.
/// A transaction is considered successful if the status code is `1`.
fn success(&self) -> bool {
match &self.status_code {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm okay with changing the status_code from U64 to u64 and use a serde_with hex_opt for this

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean #[serde(with = "hex")]?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but we can do this separately

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

given that status is always 0 or 1, I would also be comfortable just deserializing it to a bool. "real" future compatibility would be a non-exhaustive enum imho

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checked #396 , will leave this nit on that PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya sorry for stepping on your PR's toes a bit here. I feel like the infallible conversion will serve your needs better? 😅

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no worries, i like embed approach better.
one q is I had checked impl AsRef<ReceiptEnvelope> for TransactionReceipt meet the goal what this PR had supposed to, should I have to close the PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will talk internally, and then close one of them. If you like the embed approach better, we'll likely go in that direction :)

thank you for making the issue and PR regardless!

Some(status) => status == &U64::from(1),
None => false,
}
}

/// Returns the logs emitted by the transaction.
/// Converts the logs from the RPC type to the internal type.
fn logs(&self) -> Vec<PrimitivesLog<LogData>> {
rkdud007 marked this conversation as resolved.
Show resolved Hide resolved
let mut logs = Vec::new();
for log in &self.logs {
let rpc_log: Log = log.clone();
let log_data = LogData::try_from(rpc_log).unwrap_or_default();
rkdud007 marked this conversation as resolved.
Show resolved Hide resolved
let result = PrimitivesLog { address: log.address, data: log_data };
logs.push(result);
}

logs
}
}

impl TryFrom<TransactionReceipt> for ReceiptWithBloom {
type Error = ConversionError;

fn try_from(tx_receipt: TransactionReceipt) -> Result<Self, Self::Error> {
let receipt_with_bloom = ReceiptWithBloom {
receipt: Receipt {
success: tx_receipt.success(),
cumulative_gas_used: tx_receipt.cumulative_gas_used.to::<u64>(),
logs: tx_receipt.logs(),
},
bloom: tx_receipt.logs_bloom,
};
Ok(receipt_with_bloom)
}
}

impl TryFrom<TransactionReceipt> for ReceiptEnvelope {
type Error = ConversionError;

fn try_from(tx_receipt: TransactionReceipt) -> Result<Self, Self::Error> {
match tx_receipt.transaction_type.to::<u8>().try_into()? {
TxType::Legacy => Ok(ReceiptEnvelope::Legacy(tx_receipt.try_into()?)),
TxType::Eip2930 => Ok(ReceiptEnvelope::Eip2930(tx_receipt.try_into()?)),
TxType::Eip1559 => Ok(ReceiptEnvelope::Eip1559(tx_receipt.try_into()?)),
TxType::Eip4844 => Ok(ReceiptEnvelope::Eip4844(tx_receipt.try_into()?)),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn try_from_transaction_receipt_to_receipts_envelope_4844() {
// cast rpc eth_getTransactionReceipt
// 0x9c1fbda4f649ac806ab0faefbe94e1a60282eb374ead6aa01bac042f52b28a8c --rpc-url mainnet
let rpc_tx_receipt = r#"{"blobGasPrice":"0x1","blobGasUsed":"0x20000","blockHash":"0xa2917e0758c98640d868182838c93bb12f0d07b6b17efe6b62d9df42c7643791","blockNumber":"0x1286d1d","contractAddress":null,"cumulativeGasUsed":"0x56b224","effectiveGasPrice":"0xd364c1438","from":"0x40c35d4faf69234986cb599890c2d2ef546074a9","gasUsed":"0x5208","logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x0000000000000000000000000000000000000000","transactionHash":"0x9c1fbda4f649ac806ab0faefbe94e1a60282eb374ead6aa01bac042f52b28a8c","transactionIndex":"0x46","type":"0x3"}"#;
let transaction_receipt: TransactionReceipt = serde_json::from_str(rpc_tx_receipt).unwrap();

let receipt_with_bloom = ReceiptWithBloom {
receipt: Receipt { success: true, cumulative_gas_used: 0x56b224, logs: vec![] },
bloom: Bloom::default(),
};

let receipt_envelope: ReceiptEnvelope = transaction_receipt.try_into().unwrap();

assert_eq!(receipt_envelope, ReceiptEnvelope::Eip4844(receipt_with_bloom));
}

#[test]
fn try_from_transaction_receipt_to_receipts_envelope_1559() {
// cast rpc eth_getTransactionReceipt
// 0xd271efca8906538124cca4213bc61aa3def380cf5e3b068b3215c09d87219c99 --rpc-url mainnet
let rpc_tx_receipt = r#"{"blockHash":"0x851a0e708a669d9f9838c251b72d0b616b7f38c3ad38fa20a23c1144791bbdd6","blockNumber":"0x129cc66","contractAddress":null,"cumulativeGasUsed":"0x71a71f","effectiveGasPrice":"0x465e36461","from":"0xcb96aca8719987d15aecd066b7a1ad5d4d92fdd3","gasUsed":"0x74d8","logs":[{"address":"0x06450dee7fd2fb8e39061434babcfc05599a6fb8","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x000000000000000000000000cb96aca8719987d15aecd066b7a1ad5d4d92fdd3","0x00000000000000000000000085f7459e29d5626b5d2f16c00a97e0c48ce1654e"],"data":"0x000000000000000000000000000000000000000000198b0b16f55ce58edc0000","blockNumber":"0x129cc66","transactionHash":"0xd271efca8906538124cca4213bc61aa3def380cf5e3b068b3215c09d87219c99","transactionIndex":"0x7a","blockHash":"0x851a0e708a669d9f9838c251b72d0b616b7f38c3ad38fa20a23c1144791bbdd6","logIndex":"0xa9","removed":false}],"logsBloom":"0x0000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000a00010000c000000000008400010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000","status":"0x1","to":"0x06450dee7fd2fb8e39061434babcfc05599a6fb8","transactionHash":"0xd271efca8906538124cca4213bc61aa3def380cf5e3b068b3215c09d87219c99","transactionIndex":"0x7a","type":"0x2"}"#;
let transaction_receipt: TransactionReceipt = serde_json::from_str(rpc_tx_receipt).unwrap();

let receipt_envelope: ReceiptEnvelope = transaction_receipt.try_into().unwrap();

assert_eq!(receipt_envelope.tx_type(), TxType::Eip1559);
}
}