VYPR
Medium severityOSV Advisory· Published Jul 2, 2025· Updated Apr 15, 2026

CVE-2025-53359

CVE-2025-53359

Description

ethereum is a common ethereum structs for Rust. Prior to ethereum crate v0.18.0, signature malleability (according to EIP-2) was only checked for "legacy" transactions, but not for EIP-2930, EIP-1559 and EIP-7702 transactions. This is a specification deviation. The signature malleability itself is not a security issue and not as high of a risk if the ethereum crate is used on a single-implementation blockchain. This issue has been patched in version v0.18.0. A workaround for this issue involves manually checking transaction malleability outside of the crate, however upgrading is recommended.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ethereumcrates.io
< 0.18.00.18.0

Affected products

1

Patches

2
2dd9d1d5d093

Always maintain the invariant for TransactionSignature (#67)

6 files changed · +275 114
  • src/block.rs+14 10 modified
    @@ -126,10 +126,16 @@ impl From<BlockV1> for BlockV3 {
     mod tests {
     	use super::*;
     	use crate::transaction::{
    -		AuthorizationListItem, EIP7702Transaction, TransactionAction, TransactionV3,
    +		eip2930, eip7702::AuthorizationListItem, legacy::TransactionAction, EIP7702Transaction,
    +		TransactionV3,
     	};
     	use ethereum_types::{H160, H256, U256};
     
    +	const ONE: H256 = H256([
    +		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    +		0, 1,
    +	]);
    +
     	#[test]
     	fn block_v3_with_eip7702_transaction() {
     		// Create an EIP-7702 transaction
    @@ -147,13 +153,13 @@ mod tests {
     				chain_id: 1,
     				address: H160::zero(),
     				nonce: U256::zero(),
    -				y_parity: false,
    -				r: H256::zero(),
    -				s: H256::zero(),
    +				signature: eip2930::MalleableTransactionSignature {
    +					odd_y_parity: false,
    +					r: ONE,
    +					s: ONE,
    +				},
     			}],
    -			odd_y_parity: false,
    -			r: H256::zero(),
    -			s: H256::zero(),
    +			signature: eip2930::TransactionSignature::new(false, ONE, ONE).unwrap(),
     		});
     
     		// Create a block with the EIP-7702 transaction
    @@ -207,9 +213,7 @@ mod tests {
     			value: U256::zero(),
     			input: vec![],
     			access_list: vec![],
    -			odd_y_parity: false,
    -			r: H256::zero(),
    -			s: H256::zero(),
    +			signature: eip2930::TransactionSignature::new(false, ONE, ONE).unwrap(),
     		});
     
     		let partial_header = PartialHeader {
    
  • src/transaction/eip1559.rs+14 13 modified
    @@ -2,10 +2,9 @@ use ethereum_types::{H256, U256};
     use rlp::{DecoderError, Rlp, RlpStream};
     use sha3::{Digest, Keccak256};
     
    -use crate::{
    -	transaction::{AccessList, TransactionAction},
    -	Bytes,
    -};
    +use crate::Bytes;
    +
    +pub use super::eip2930::{AccessList, TransactionAction, TransactionSignature};
     
     #[derive(Clone, Debug, PartialEq, Eq)]
     #[cfg_attr(
    @@ -28,9 +27,7 @@ pub struct EIP1559Transaction {
     	pub value: U256,
     	pub input: Bytes,
     	pub access_list: AccessList,
    -	pub odd_y_parity: bool,
    -	pub r: H256,
    -	pub s: H256,
    +	pub signature: TransactionSignature,
     }
     
     impl EIP1559Transaction {
    @@ -69,9 +66,9 @@ impl rlp::Encodable for EIP1559Transaction {
     		s.append(&self.value);
     		s.append(&self.input);
     		s.append_list(&self.access_list);
    -		s.append(&self.odd_y_parity);
    -		s.append(&U256::from_big_endian(&self.r[..]));
    -		s.append(&U256::from_big_endian(&self.s[..]));
    +		s.append(&self.signature.odd_y_parity());
    +		s.append(&U256::from_big_endian(&self.signature.r()[..]));
    +		s.append(&U256::from_big_endian(&self.signature.s()[..]));
     	}
     }
     
    @@ -91,9 +88,13 @@ impl rlp::Decodable for EIP1559Transaction {
     			value: rlp.val_at(6)?,
     			input: rlp.val_at(7)?,
     			access_list: rlp.list_at(8)?,
    -			odd_y_parity: rlp.val_at(9)?,
    -			r: H256::from(rlp.val_at::<U256>(10)?.to_big_endian()),
    -			s: H256::from(rlp.val_at::<U256>(11)?.to_big_endian()),
    +			signature: {
    +				let odd_y_parity = rlp.val_at(9)?;
    +				let r = H256::from(rlp.val_at::<U256>(10)?.to_big_endian());
    +				let s = H256::from(rlp.val_at::<U256>(11)?.to_big_endian());
    +				TransactionSignature::new(odd_y_parity, r, s)
    +					.ok_or(DecoderError::Custom("Invalid transaction signature format"))?
    +			},
     		})
     	}
     }
    
  • src/transaction/eip2930.rs+122 10 modified
    @@ -4,7 +4,117 @@ use ethereum_types::{Address, H256, U256};
     use rlp::{DecoderError, Rlp, RlpStream};
     use sha3::{Digest, Keccak256};
     
    -use crate::{transaction::TransactionAction, Bytes};
    +use crate::Bytes;
    +
    +pub use super::legacy::TransactionAction;
    +
    +#[derive(Clone, Debug, PartialEq, Eq)]
    +#[cfg_attr(
    +	feature = "with-scale",
    +	derive(
    +		scale_info::TypeInfo,
    +		scale_codec::Encode,
    +		scale_codec::Decode,
    +		scale_codec::DecodeWithMemTracking
    +	)
    +)]
    +#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
    +pub struct MalleableTransactionSignature {
    +	pub odd_y_parity: bool,
    +	pub r: H256,
    +	pub s: H256,
    +}
    +
    +#[derive(Clone, Debug, PartialEq, Eq)]
    +#[cfg_attr(
    +	feature = "with-scale",
    +	derive(
    +		scale_info::TypeInfo,
    +		scale_codec::Encode,
    +		scale_codec::DecodeWithMemTracking
    +	)
    +)]
    +#[cfg_attr(feature = "with-serde", derive(serde::Serialize))]
    +pub struct TransactionSignature {
    +	odd_y_parity: bool,
    +	r: H256,
    +	s: H256,
    +}
    +
    +impl TransactionSignature {
    +	#[must_use]
    +	pub fn new(odd_y_parity: bool, r: H256, s: H256) -> Option<Self> {
    +		const LOWER: H256 = H256([
    +			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    +			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    +			0x00, 0x00, 0x00, 0x01,
    +		]);
    +		const UPPER: H256 = H256([
    +			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    +			0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c,
    +			0xd0, 0x36, 0x41, 0x41,
    +		]);
    +
    +		let is_valid = r < UPPER && r >= LOWER && s < UPPER && s >= LOWER;
    +
    +		if is_valid {
    +			Some(Self { odd_y_parity, r, s })
    +		} else {
    +			None
    +		}
    +	}
    +
    +	#[must_use]
    +	pub fn odd_y_parity(&self) -> bool {
    +		self.odd_y_parity
    +	}
    +
    +	#[must_use]
    +	pub fn r(&self) -> &H256 {
    +		&self.r
    +	}
    +
    +	#[must_use]
    +	pub fn s(&self) -> &H256 {
    +		&self.s
    +	}
    +
    +	#[must_use]
    +	pub fn is_low_s(&self) -> bool {
    +		const LOWER: H256 = H256([
    +			0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
    +			0xff, 0xff, 0x5d, 0x57, 0x6e, 0x73, 0x57, 0xa4, 0x50, 0x1d, 0xdf, 0xe9, 0x2f, 0x46,
    +			0x68, 0x1b, 0x20, 0xa0,
    +		]);
    +
    +		self.s <= LOWER
    +	}
    +}
    +
    +#[cfg(feature = "with-scale")]
    +impl scale_codec::Decode for TransactionSignature {
    +	fn decode<I: scale_codec::Input>(value: &mut I) -> Result<Self, scale_codec::Error> {
    +		let unchecked = MalleableTransactionSignature::decode(value)?;
    +		match Self::new(unchecked.odd_y_parity, unchecked.r, unchecked.s) {
    +			Some(signature) => Ok(signature),
    +			None => Err(scale_codec::Error::from("Invalid signature")),
    +		}
    +	}
    +}
    +
    +#[cfg(feature = "with-serde")]
    +impl<'de> serde::Deserialize<'de> for TransactionSignature {
    +	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    +	where
    +		D: serde::de::Deserializer<'de>,
    +	{
    +		let unchecked = MalleableTransactionSignature::deserialize(deserializer)?;
    +		Ok(
    +			TransactionSignature::new(unchecked.odd_y_parity, unchecked.r, unchecked.s)
    +				.ok_or(serde::de::Error::custom("invalid signature"))?,
    +		)
    +	}
    +}
     
     #[derive(Clone, Debug, PartialEq, Eq)]
     #[cfg_attr(
    @@ -61,9 +171,7 @@ pub struct EIP2930Transaction {
     	pub value: U256,
     	pub input: Bytes,
     	pub access_list: AccessList,
    -	pub odd_y_parity: bool,
    -	pub r: H256,
    -	pub s: H256,
    +	pub signature: TransactionSignature,
     }
     
     impl EIP2930Transaction {
    @@ -100,9 +208,9 @@ impl rlp::Encodable for EIP2930Transaction {
     		s.append(&self.value);
     		s.append(&self.input);
     		s.append_list(&self.access_list);
    -		s.append(&self.odd_y_parity);
    -		s.append(&U256::from_big_endian(&self.r[..]));
    -		s.append(&U256::from_big_endian(&self.s[..]));
    +		s.append(&self.signature.odd_y_parity());
    +		s.append(&U256::from_big_endian(&self.signature.r()[..]));
    +		s.append(&U256::from_big_endian(&self.signature.s()[..]));
     	}
     }
     
    @@ -121,9 +229,13 @@ impl rlp::Decodable for EIP2930Transaction {
     			value: rlp.val_at(5)?,
     			input: rlp.val_at(6)?,
     			access_list: rlp.list_at(7)?,
    -			odd_y_parity: rlp.val_at(8)?,
    -			r: H256::from(rlp.val_at::<U256>(9)?.to_big_endian()),
    -			s: H256::from(rlp.val_at::<U256>(10)?.to_big_endian()),
    +			signature: {
    +				let odd_y_parity = rlp.val_at(8)?;
    +				let r = H256::from(rlp.val_at::<U256>(9)?.to_big_endian());
    +				let s = H256::from(rlp.val_at::<U256>(10)?.to_big_endian());
    +				TransactionSignature::new(odd_y_parity, r, s)
    +					.ok_or(DecoderError::Custom("Invalid transaction signature format"))?
    +			},
     		})
     	}
     }
    
  • src/transaction/eip7702.rs+61 52 modified
    @@ -5,9 +5,10 @@ use k256::ecdsa::{RecoveryId, Signature, VerifyingKey};
     use rlp::{DecoderError, Rlp, RlpStream};
     use sha3::{Digest, Keccak256};
     
    -use crate::{
    -	transaction::{AccessList, TransactionAction},
    -	Bytes,
    +use crate::Bytes;
    +
    +pub use super::eip2930::{
    +	AccessList, MalleableTransactionSignature, TransactionAction, TransactionSignature,
     };
     
     /// Error type for EIP-7702 authorization signature recovery
    @@ -45,9 +46,7 @@ pub struct AuthorizationListItem {
     	pub chain_id: u64,
     	pub address: Address,
     	pub nonce: U256,
    -	pub y_parity: bool,
    -	pub r: H256,
    -	pub s: H256,
    +	pub signature: MalleableTransactionSignature,
     }
     
     impl rlp::Encodable for AuthorizationListItem {
    @@ -56,9 +55,9 @@ impl rlp::Encodable for AuthorizationListItem {
     		s.append(&self.chain_id);
     		s.append(&self.address);
     		s.append(&self.nonce);
    -		s.append(&self.y_parity);
    -		s.append(&U256::from_big_endian(&self.r[..]));
    -		s.append(&U256::from_big_endian(&self.s[..]));
    +		s.append(&self.signature.odd_y_parity);
    +		s.append(&U256::from_big_endian(&self.signature.r[..]));
    +		s.append(&U256::from_big_endian(&self.signature.s[..]));
     	}
     }
     
    @@ -72,29 +71,48 @@ impl rlp::Decodable for AuthorizationListItem {
     			chain_id: rlp.val_at(0)?,
     			address: rlp.val_at(1)?,
     			nonce: rlp.val_at(2)?,
    -			y_parity: rlp.val_at(3)?,
    -			r: H256::from(rlp.val_at::<U256>(4)?.to_big_endian()),
    -			s: H256::from(rlp.val_at::<U256>(5)?.to_big_endian()),
    +			signature: {
    +				let odd_y_parity = rlp.val_at(3)?;
    +				let r = H256::from(rlp.val_at::<U256>(4)?.to_big_endian());
    +				let s = H256::from(rlp.val_at::<U256>(5)?.to_big_endian());
    +				MalleableTransactionSignature { odd_y_parity, r, s }
    +			},
     		})
     	}
     }
     
     impl AuthorizationListItem {
    +	/// Check and get the signature.
    +	///
    +	/// This checks that the signature is not malleable, but does not otherwise check or recover
    +	/// the public key.
    +	pub fn signature(&self) -> Option<TransactionSignature> {
    +		TransactionSignature::new(
    +			self.signature.odd_y_parity,
    +			self.signature.r,
    +			self.signature.s,
    +		)
    +	}
    +
     	/// Recover the authorizing address from the authorization signature according to EIP-7702
     	pub fn authorizing_address(&self) -> Result<Address, AuthorizationError> {
     		// Create the authorization message hash according to EIP-7702
     		let message_hash = self.authorization_message_hash();
     
    +		let sigv = self
    +			.signature()
    +			.ok_or(AuthorizationError::InvalidSignature)?;
    +
     		// Create signature from r and s components
     		let mut signature_bytes = [0u8; 64];
    -		signature_bytes[0..32].copy_from_slice(&self.r[..]);
    -		signature_bytes[32..64].copy_from_slice(&self.s[..]);
    +		signature_bytes[0..32].copy_from_slice(&sigv.r()[..]);
    +		signature_bytes[32..64].copy_from_slice(&sigv.s()[..]);
     
     		// Create the signature and recovery ID
     		let signature = Signature::from_bytes(&signature_bytes.into())
     			.map_err(|_| AuthorizationError::InvalidSignature)?;
     
    -		let recovery_id = RecoveryId::try_from(if self.y_parity { 1u8 } else { 0u8 })
    +		let recovery_id = RecoveryId::try_from(if sigv.odd_y_parity() { 1u8 } else { 0u8 })
     			.map_err(|_| AuthorizationError::InvalidRecoveryId)?;
     
     		// Recover the verifying key using VerifyingKey::recover_from_prehash
    @@ -169,9 +187,7 @@ pub struct EIP7702Transaction {
     	pub data: Bytes,
     	pub access_list: AccessList,
     	pub authorization_list: AuthorizationList,
    -	pub odd_y_parity: bool,
    -	pub r: H256,
    -	pub s: H256,
    +	pub signature: TransactionSignature,
     }
     
     impl EIP7702Transaction {
    @@ -212,9 +228,9 @@ impl rlp::Encodable for EIP7702Transaction {
     		s.append(&self.data);
     		s.append_list(&self.access_list);
     		s.append_list(&self.authorization_list);
    -		s.append(&self.odd_y_parity);
    -		s.append(&U256::from_big_endian(&self.r[..]));
    -		s.append(&U256::from_big_endian(&self.s[..]));
    +		s.append(&self.signature.odd_y_parity());
    +		s.append(&U256::from_big_endian(&self.signature.r()[..]));
    +		s.append(&U256::from_big_endian(&self.signature.s()[..]));
     	}
     }
     
    @@ -235,9 +251,13 @@ impl rlp::Decodable for EIP7702Transaction {
     			data: rlp.val_at(7)?,
     			access_list: rlp.list_at(8)?,
     			authorization_list: rlp.list_at(9)?,
    -			odd_y_parity: rlp.val_at(10)?,
    -			r: H256::from(rlp.val_at::<U256>(11)?.to_big_endian()),
    -			s: H256::from(rlp.val_at::<U256>(12)?.to_big_endian()),
    +			signature: {
    +				let odd_y_parity = rlp.val_at(10)?;
    +				let r = H256::from(rlp.val_at::<U256>(11)?.to_big_endian());
    +				let s = H256::from(rlp.val_at::<U256>(12)?.to_big_endian());
    +				TransactionSignature::new(odd_y_parity, r, s)
    +					.ok_or(DecoderError::Custom("Invalid transaction signature format"))?
    +			},
     		})
     	}
     }
    @@ -340,9 +360,11 @@ mod tests {
     			chain_id,
     			address,
     			nonce,
    -			y_parity,
    -			r,
    -			s,
    +			signature: MalleableTransactionSignature {
    +				odd_y_parity: y_parity,
    +				r,
    +				s,
    +			},
     		};
     
     		// Recover the authorizing address
    @@ -371,34 +393,21 @@ mod tests {
     	#[test]
     	fn test_authorizing_address_error_handling() {
     		// Test with invalid signature components (zero values are invalid in ECDSA)
    -		let auth_item = AuthorizationListItem {
    -			chain_id: 1,
    -			address: Address::from_slice(&[0x42u8; 20]),
    -			nonce: U256::zero(),
    -			y_parity: false,
    -			r: H256::zero(), // Invalid r value (r cannot be zero)
    -			s: H256::zero(), // Invalid s value (s cannot be zero)
    -		};
    -
    -		// This should return an error due to invalid signature
    -		let result = auth_item.authorizing_address();
    -		assert!(result.is_err());
    -		assert_eq!(result.unwrap_err(), AuthorizationError::InvalidSignature);
    +		assert!(TransactionSignature::new(
    +			false,
    +			H256::zero(), // Invalid r value (r cannot be zero)
    +			H256::zero(), // Invalid s value (s cannot be zero)
    +		)
    +		.is_none());
     
     		// Test with values that are too high (greater than secp256k1 curve order)
     		// secp256k1 curve order is FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
    -		let auth_item_high_values = AuthorizationListItem {
    -			chain_id: 1,
    -			address: Address::from_slice(&[0x42u8; 20]),
    -			nonce: U256::zero(),
    -			y_parity: false,
    +		assert!(TransactionSignature::new(
    +			false,
     			// Use maximum possible values which exceed the curve order
    -			r: H256::from_slice(&[0xFF; 32]),
    -			s: H256::from_slice(&[0xFF; 32]),
    -		};
    -
    -		let result = auth_item_high_values.authorizing_address();
    -		assert!(result.is_err());
    -		assert_eq!(result.unwrap_err(), AuthorizationError::InvalidSignature);
    +			H256::from_slice(&[0xFF; 32]),
    +			H256::from_slice(&[0xFF; 32]),
    +		)
    +		.is_none());
     	}
     }
    
  • src/transaction/legacy.rs+24 1 modified
    @@ -91,7 +91,7 @@ impl TransactionRecoveryId {
     	feature = "with-scale",
     	derive(scale_info::TypeInfo, scale_codec::DecodeWithMemTracking)
     )]
    -#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))]
    +#[cfg_attr(feature = "with-serde", derive(serde::Serialize))]
     pub struct TransactionSignature {
     	v: TransactionRecoveryId,
     	r: H256,
    @@ -181,6 +181,29 @@ impl scale_codec::Decode for TransactionSignature {
     	}
     }
     
    +#[cfg(feature = "with-serde")]
    +#[derive(serde::Deserialize)]
    +struct TransactionSignatureUnchecked {
    +	v: u64,
    +	r: H256,
    +	s: H256,
    +}
    +
    +#[cfg(feature = "with-serde")]
    +impl<'de> serde::Deserialize<'de> for TransactionSignature {
    +	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    +	where
    +		D: serde::de::Deserializer<'de>,
    +	{
    +		let unchecked = TransactionSignatureUnchecked::deserialize(deserializer)?;
    +
    +		Ok(
    +			TransactionSignature::new(unchecked.v, unchecked.r, unchecked.s)
    +				.ok_or(serde::de::Error::custom("invalid signature"))?,
    +		)
    +	}
    +}
    +
     #[derive(Clone, Debug, PartialEq, Eq)]
     #[cfg_attr(
     	feature = "with-scale",
    
  • src/transaction/mod.rs+40 28 modified
    @@ -1,23 +1,15 @@
    -mod eip1559;
    -mod eip2930;
    -mod eip7702;
    -mod legacy;
    +pub mod eip1559;
    +pub mod eip2930;
    +pub mod eip7702;
    +pub mod legacy;
     
     use bytes::BytesMut;
     use ethereum_types::H256;
     use rlp::{DecoderError, Rlp};
     
     pub use self::{
    -	eip1559::{EIP1559Transaction, EIP1559TransactionMessage},
    -	eip2930::{AccessList, AccessListItem, EIP2930Transaction, EIP2930TransactionMessage},
    -	eip7702::{
    -		AuthorizationList, AuthorizationListItem, EIP7702Transaction, EIP7702TransactionMessage,
    -		AUTHORIZATION_MAGIC, SET_CODE_TX_TYPE,
    -	},
    -	legacy::{
    -		LegacyTransaction, LegacyTransactionMessage, TransactionAction, TransactionRecoveryId,
    -		TransactionSignature,
    -	},
    +	eip1559::EIP1559Transaction, eip2930::EIP2930Transaction, eip7702::EIP7702Transaction,
    +	legacy::LegacyTransaction,
     };
     use crate::enveloped::{EnvelopedDecodable, EnvelopedDecoderError, EnvelopedEncodable};
     
    @@ -328,7 +320,14 @@ pub type TransactionAny = TransactionV3;
     
     #[cfg(test)]
     mod tests {
    -	use super::*;
    +	use super::{
    +		eip2930::{self, AccessListItem},
    +		eip7702::AuthorizationListItem,
    +		legacy::{self, TransactionAction},
    +		EIP1559Transaction, EIP2930Transaction, EIP7702Transaction, EnvelopedDecodable,
    +		TransactionV0, TransactionV1, TransactionV2, TransactionV3,
    +	};
    +	use crate::enveloped::*;
     	use ethereum_types::U256;
     	use hex_literal::hex;
     
    @@ -353,7 +352,7 @@ mod tests {
     			),
     			value: U256::from(10) * 1_000_000_000 * 1_000_000_000,
     			input: hex!("a9059cbb000000000213ed0f886efd100b67c7e4ec0a85a7d20dc971600000000000000000000015af1d78b58c4000").into(),
    -			signature: TransactionSignature::new(38, hex!("be67e0a07db67da8d446f76add590e54b6e92cb6b8f9835aeb67540579a27717").into(), hex!("2d690516512020171c1ec870f6ff45398cc8609250326be89915fb538e7bd718").into()).unwrap(),
    +			signature: legacy::TransactionSignature::new(38, hex!("be67e0a07db67da8d446f76add590e54b6e92cb6b8f9835aeb67540579a27717").into(), hex!("2d690516512020171c1ec870f6ff45398cc8609250326be89915fb538e7bd718").into()).unwrap(),
     		};
     
     		assert_eq!(
    @@ -389,9 +388,12 @@ mod tests {
     					storage_keys: vec![],
     				},
     			],
    -			odd_y_parity: false,
    -			r: hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0").into(),
    -			s: hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094").into(),
    +			signature: eip2930::TransactionSignature::new(
    +				false,
    +				hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0").into(),
    +				hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094").into(),
    +			)
    +			.unwrap(),
     		});
     
     		assert_eq!(
    @@ -428,9 +430,12 @@ mod tests {
     					storage_keys: vec![],
     				},
     			],
    -			odd_y_parity: false,
    -			r: hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0").into(),
    -			s: hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094").into(),
    +			signature: eip2930::TransactionSignature::new(
    +				false,
    +				hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0").into(),
    +				hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094").into(),
    +			)
    +			.unwrap(),
     		});
     
     		assert_eq!(
    @@ -463,13 +468,20 @@ mod tests {
     				chain_id: 5,
     				address: hex!("de0b295669a9fd93d5f28d9ec85e40f4cb697bae").into(),
     				nonce: 1.into(),
    -				y_parity: false,
    -				r: hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0").into(),
    -				s: hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094").into(),
    +				signature: eip2930::MalleableTransactionSignature {
    +					odd_y_parity: false,
    +					r: hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0")
    +						.into(),
    +					s: hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094")
    +						.into(),
    +				},
     			}],
    -			odd_y_parity: false,
    -			r: hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0").into(),
    -			s: hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094").into(),
    +			signature: eip2930::TransactionSignature::new(
    +				false,
    +				hex!("36b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc0903590c16b02b0").into(),
    +				hex!("5edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094").into(),
    +			)
    +			.unwrap(),
     		});
     
     		assert_eq!(
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.