Skip to content

Commit

Permalink
chain, graph: Add evaluate_transaction_status function
Browse files Browse the repository at this point in the history
  • Loading branch information
tilacog committed Jul 9, 2021
1 parent 74d3f3d commit cbbad79
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 41 deletions.
22 changes: 1 addition & 21 deletions chain/ethereum/src/ethereum_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1752,7 +1752,7 @@ async fn filter_call_triggers_from_unsuccessful_transactions(
for (transaction, receipt) in receipts_and_transactions.into_iter() {
transaction_success.insert(
&transaction.hash,
is_transaction_successful(&transaction, &receipt)?,
evaluate_transaction_status(receipt.status, receipt.gas_used, &transaction.gas)?,
);
}

Expand All @@ -1776,23 +1776,3 @@ async fn filter_call_triggers_from_unsuccessful_transactions(
});
Ok(block)
}

/// Evaluates if a given transaction was successful.
///
/// According to EIP-658, there are two ways of checking if a transaction failed:
/// 1. by checking if it ran out of gas.
/// 2. by looking at its receipt "status" boolean field, which may be absent for blocks before
/// Byzantium fork.
fn is_transaction_successful(
transaction: &Transaction,
receipt: &LightTransactionReceipt,
) -> anyhow::Result<bool> {
if let Some(status) = receipt.is_sucessful() {
Ok(status)
} else {
let gas_used = receipt
.gas_used
.ok_or(anyhow::anyhow!("Running in light client mode"))?;
Ok(gas_used >= transaction.gas)
}
}
3 changes: 2 additions & 1 deletion graph/src/components/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use web3::types::H256;

pub use self::network::NodeCapabilities;
pub use self::types::{
EthereumBlock, EthereumBlockWithCalls, EthereumCall, LightEthereumBlock, LightEthereumBlockExt,
evaluate_transaction_status, EthereumBlock, EthereumBlockWithCalls, EthereumCall,
LightEthereumBlock, LightEthereumBlockExt,
};

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
Expand Down
30 changes: 21 additions & 9 deletions graph/src/components/ethereum/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use serde::{Deserialize, Serialize};
use std::{convert::TryFrom, sync::Arc};
use web3::types::{
Action, Address, Block, Bytes, Log, Res, Trace, Transaction, TransactionReceipt, H256, U256,
U64,
};

use crate::{
Expand Down Expand Up @@ -91,15 +92,26 @@ impl EthereumBlockWithCalls {
"failed to find the transaction for this call"
))?;

// assume the transaction failed if all gas was used
if receipt
.gas_used
.ok_or(anyhow::anyhow!("Running in light client mode)"))?
>= transaction.gas
{
return Ok(false);
}
Ok(matches!(receipt.status, Some(x) if x == web3::types::U64::from(1)))
evaluate_transaction_status(receipt.status, receipt.gas_used, &transaction.gas)
}
}

/// Evaluates if a given transaction was successful.
///
/// According to EIP-658, there are two ways of checking if a transaction failed:
/// 1. by checking if it ran out of gas.
/// 2. by looking at its receipt "status" boolean field, which may be absent for blocks before
/// Byzantium fork.
pub fn evaluate_transaction_status(
receipt_status: Option<U64>,
receipt_gas_used: Option<U256>,
transaction_gas: &U256,
) -> anyhow::Result<bool> {
if receipt_gas_used.ok_or(anyhow::anyhow!("Running in light client mode)"))? >= *transaction_gas
{
Ok(false)
} else {
Ok(matches!(receipt_status, Some(status) if !status.is_zero()))
}
}

Expand Down
10 changes: 0 additions & 10 deletions graph/src/components/transaction_receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,6 @@ pub struct LightTransactionReceipt {
pub status: Option<U64>,
}

impl LightTransactionReceipt {
/// `0x0` indicates transaction failure, `0x1` indicates transaction success.
/// Set for blocks mined after Byzantium hard fork, `None` before.
///
/// Relevant EIPs: 609, 658
pub fn is_sucessful(&self) -> Option<bool> {
self.status.map(|status| !status.is_zero())
}
}

/// Converts Vec<u8> to [u8; N], where N is the vector's expected lenght.
/// Fails if input size is larger than output size.
pub(crate) fn drain_vector<const N: usize>(input: Vec<u8>) -> Result<[u8; N], anyhow::Error> {
Expand Down

0 comments on commit cbbad79

Please sign in to comment.