diff --git a/crates/ethereum/evm/src/execute.rs b/crates/ethereum/evm/src/execute.rs
index 90a59afcc..250422032 100644
--- a/crates/ethereum/evm/src/execute.rs
+++ b/crates/ethereum/evm/src/execute.rs
@@ -23,7 +23,7 @@ use reth_execution_types::BlockExecutionResult;
use reth_primitives::{
EthPrimitives, Receipt, Recovered, RecoveredBlock, SealedBlock, TransactionSigned,
};
-use reth_primitives_traits::{transaction::signed::HL_SYSTEM_TX_FROM_ADDR, NodePrimitives};
+use reth_primitives_traits::{transaction::signed::is_impersonated_tx, NodePrimitives};
use reth_revm::{context_interface::result::ResultAndState, db::State, DatabaseCommit};
/// Factory for [`EthExecutionStrategy`].
@@ -191,7 +191,7 @@ where
}
let hash = tx.hash();
- let is_system_transaction = tx.signer() == HL_SYSTEM_TX_FROM_ADDR;
+ let is_system_transaction = is_impersonated_tx(tx.signature(), tx.gas_price()).is_some();
// Execute transaction.
let result_and_state =
diff --git a/crates/ethereum/primitives/src/transaction.rs b/crates/ethereum/primitives/src/transaction.rs
index 9196c6669..bbd71f9de 100644
--- a/crates/ethereum/primitives/src/transaction.rs
+++ b/crates/ethereum/primitives/src/transaction.rs
@@ -21,7 +21,7 @@ use reth_primitives_traits::{
sync::OnceLock,
transaction::{
error::TransactionConversionError,
- signed::{is_impersonated_tx, RecoveryError, HL_SYSTEM_TX_FROM_ADDR},
+ signed::{is_impersonated_tx, RecoveryError},
},
InMemorySize, SignedTransaction,
};
@@ -836,8 +836,8 @@ impl SignedTransaction for TransactionSigned {
fn recover_signer(&self) -> Result
{
let signature = self.signature();
- if is_impersonated_tx(signature, self.gas_price()) {
- return Ok(HL_SYSTEM_TX_FROM_ADDR);
+ if let Some(address) = is_impersonated_tx(signature, self.gas_price()) {
+ return Ok(address);
}
let signature_hash = self.signature_hash();
recover_signer(&self.signature, signature_hash)
diff --git a/crates/payload/validator/src/lib.rs b/crates/payload/validator/src/lib.rs
index 878f1cf21..ae77c25b1 100644
--- a/crates/payload/validator/src/lib.rs
+++ b/crates/payload/validator/src/lib.rs
@@ -15,7 +15,7 @@ pub mod shanghai;
use alloy_rpc_types_engine::{ExecutionData, PayloadError};
use reth_chainspec::EthereumHardforks;
use reth_primitives::SealedBlock;
-use reth_primitives_traits::transaction::signed::HL_SYSTEM_TX_FROM_ADDR;
+use reth_primitives_traits::transaction::signed::is_impersonated_tx;
use reth_primitives_traits::{Block, SignedTransaction};
use std::sync::Arc;
@@ -94,9 +94,7 @@ impl ExecutionPayloadValidator {
let (normal, system) = transactions.into_iter().partition(|tx| {
let tx = T::decode_2718(&mut tx.iter().as_slice());
match tx {
- Ok(tx) => {
- !matches!(tx.recover_signer(), Ok(address) if HL_SYSTEM_TX_FROM_ADDR == address)
- }
+ Ok(tx) => is_impersonated_tx(tx.signature(), tx.gas_price()).is_none(),
Err(_) => true,
}
});
diff --git a/crates/primitives-traits/src/block/body.rs b/crates/primitives-traits/src/block/body.rs
index 75131b28c..21af49458 100644
--- a/crates/primitives-traits/src/block/body.rs
+++ b/crates/primitives-traits/src/block/body.rs
@@ -1,7 +1,7 @@
//! Block body abstraction.
use crate::{
- transaction::signed::{RecoveryError, HL_SYSTEM_TX_FROM_ADDR},
+ transaction::signed::{is_impersonated_tx, RecoveryError},
BlockHeader, FullSignedTx, InMemorySize, MaybeSerde, MaybeSerdeBincodeCompat,
SignedTransaction,
};
@@ -85,7 +85,7 @@ pub trait BlockBody:
let transactions: Vec = self
.transactions()
.into_iter()
- .filter(|tx| !matches!(tx.recover_signer(), Ok(address) if HL_SYSTEM_TX_FROM_ADDR == address))
+ .filter(|&tx| is_impersonated_tx(tx.signature(), tx.gas_price()).is_none())
.cloned()
.collect::>();
alloy_consensus::proofs::calculate_transaction_root(transactions.as_slice())
diff --git a/crates/primitives-traits/src/transaction/signed.rs b/crates/primitives-traits/src/transaction/signed.rs
index 1399db331..41ae8f7d3 100644
--- a/crates/primitives-traits/src/transaction/signed.rs
+++ b/crates/primitives-traits/src/transaction/signed.rs
@@ -10,9 +10,10 @@ use alloy_consensus::{
SignableTransaction, Transaction,
};
use alloy_eips::eip2718::{Decodable2718, Encodable2718};
-use alloy_primitives::{keccak256, Address, PrimitiveSignature as Signature, TxHash, B256};
+use alloy_primitives::{keccak256, Address, PrimitiveSignature as Signature, TxHash, B256, U160};
use core::hash::Hash;
use revm_primitives::{address, U256};
+use std::ops::Add;
/// Helper trait that unifies all behaviour required by block to support full node operations.
pub trait FullSignedTx: SignedTransaction + MaybeCompact + MaybeSerdeBincodeCompat {}
@@ -23,11 +24,20 @@ pub const HL_SYSTEM_TX_FROM_ADDR: Address = address!("22222222222222222222222222
/// Check if the transaction is impersonated.
/// Signature part is introduced in block_ingest, while the gas_price is trait of hyperliquid system transactions.
-pub fn is_impersonated_tx(signature: &Signature, gas_price: Option) -> bool {
- signature.r() == U256::from(1)
- && signature.s() == U256::from(1)
- && signature.v() == true
- && gas_price == Some(0u128)
+pub fn is_impersonated_tx(signature: &Signature, gas_price: Option) -> Option {
+ if signature.r() == U256::from(1) && signature.v() == true && gas_price == Some(0u128) {
+ if signature.s() == U256::from(1) {
+ Some(HL_SYSTEM_TX_FROM_ADDR)
+ } else {
+ let s = signature.s().reduce_mod(U256::from(U160::MAX).add(U256::from(1)));
+ let s = U160::from(s);
+ let s: [u8; 20] = s.to_be_bytes();
+ let s = Address::from_slice(&s);
+ Some(s)
+ }
+ } else {
+ None
+ }
}
/// A signed transaction.
@@ -89,8 +99,8 @@ pub trait SignedTransaction:
/// Returns `None` if the transaction's signature is invalid, see also
/// `reth_primitives::transaction::recover_signer_unchecked`.
fn recover_signer_unchecked(&self) -> Result {
- if is_impersonated_tx(self.signature(), self.gas_price()) {
- return Ok(HL_SYSTEM_TX_FROM_ADDR);
+ if let Some(address) = is_impersonated_tx(self.signature(), self.gas_price()) {
+ return Ok(address);
}
self.recover_signer_unchecked_with_buf(&mut Vec::new()).map_err(|_| RecoveryError)
}
@@ -183,8 +193,8 @@ impl SignedTransaction for PooledTransaction {
buf: &mut Vec,
) -> Result {
let signature = self.signature();
- if is_impersonated_tx(signature, self.gas_price()) {
- return Ok(HL_SYSTEM_TX_FROM_ADDR);
+ if let Some(address) = is_impersonated_tx(signature, self.gas_price()) {
+ return Ok(address);
}
match self {
Self::Legacy(tx) => tx.tx().encode_for_signing(buf),