From bf4aa42884fa0bec40f314163040f33c0f825800 Mon Sep 17 00:00:00 2001 From: Jonathan LEI Date: Sat, 9 Apr 2022 01:58:26 +0800 Subject: [PATCH] fix: fix deploy tx RLP decoding (#1124) * fix: fix deploy tx RLP decoding * refactor: move duplicate RLP code into helper function --- ethers-core/src/types/transaction/eip1559.rs | 5 ++-- ethers-core/src/types/transaction/eip2718.rs | 8 +++++++ ethers-core/src/types/transaction/eip2930.rs | 5 ++-- ethers-core/src/types/transaction/mod.rs | 24 ++++++++++++++++++++ ethers-core/src/types/transaction/request.rs | 5 ++-- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/ethers-core/src/types/transaction/eip1559.rs b/ethers-core/src/types/transaction/eip1559.rs index df42c7ed..cea028c9 100644 --- a/ethers-core/src/types/transaction/eip1559.rs +++ b/ethers-core/src/types/transaction/eip1559.rs @@ -1,4 +1,4 @@ -use super::{eip2930::AccessList, normalize_v, rlp_opt}; +use super::{decode_to, eip2930::AccessList, normalize_v, rlp_opt}; use crate::{ types::{Address, Bytes, NameOrAddress, Signature, Transaction, H256, U256, U64}, utils::keccak256, @@ -199,8 +199,7 @@ impl Eip1559TransactionRequest { *offset += 1; self.gas = Some(rlp.val_at(*offset)?); *offset += 1; - self.to = Some(rlp.val_at(*offset)?); - *offset += 1; + self.to = decode_to(rlp, offset)?; self.value = Some(rlp.val_at(*offset)?); *offset += 1; let data = rlp::Rlp::new(rlp.at(*offset)?.as_raw()).data()?; diff --git a/ethers-core/src/types/transaction/eip2718.rs b/ethers-core/src/types/transaction/eip2718.rs index 86ffa64a..a64ef657 100644 --- a/ethers-core/src/types/transaction/eip2718.rs +++ b/ethers-core/src/types/transaction/eip2718.rs @@ -455,4 +455,12 @@ mod tests { let decoded_transaction = TypedTransaction::decode(&expected_rlp).unwrap(); assert_eq!(tx.sighash(), decoded_transaction.sighash()); } + + #[test] + fn test_eip1559_deploy_tx_decode() { + let typed_tx_hex = + hex::decode("02dc8205058193849502f90085010c388d00837a120080808411223344c0").unwrap(); + let tx_rlp = rlp::Rlp::new(typed_tx_hex.as_slice()); + TypedTransaction::decode(&tx_rlp).unwrap(); + } } diff --git a/ethers-core/src/types/transaction/eip2930.rs b/ethers-core/src/types/transaction/eip2930.rs index 1662382e..39c3e2b6 100644 --- a/ethers-core/src/types/transaction/eip2930.rs +++ b/ethers-core/src/types/transaction/eip2930.rs @@ -1,4 +1,4 @@ -use super::{normalize_v, request::TransactionRequest}; +use super::{decode_to, normalize_v, request::TransactionRequest}; use crate::types::{Address, Bytes, Signature, Transaction, H256, U256, U64}; use rlp::{Decodable, DecoderError, RlpStream}; @@ -117,8 +117,7 @@ impl Eip2930TransactionRequest { self.tx.gas = Some(rlp.val_at(*offset)?); *offset += 1; - self.tx.to = Some(rlp.val_at(*offset)?); - *offset += 1; + self.tx.to = decode_to(rlp, offset)?; self.tx.value = Some(rlp.val_at(*offset)?); *offset += 1; let data = rlp::Rlp::new(rlp.at(*offset)?.as_raw()).data()?; diff --git a/ethers-core/src/types/transaction/mod.rs b/ethers-core/src/types/transaction/mod.rs index b4a25e97..04996c05 100644 --- a/ethers-core/src/types/transaction/mod.rs +++ b/ethers-core/src/types/transaction/mod.rs @@ -60,6 +60,30 @@ fn decode_signature( Ok(sig) } +/// Decodes the `to` field of the RLP encoding based on the RLP offset passed. Increments the offset +/// by one. +#[inline] +fn decode_to( + rlp: &rlp::Rlp, + offset: &mut usize, +) -> Result, rlp::DecoderError> { + let to = { + let to = rlp.at(*offset)?; + if to.is_empty() { + if to.is_data() { + None + } else { + return Err(rlp::DecoderError::RlpExpectedToBeData) + } + } else { + Some(to.as_val()?) + } + }; + *offset += 1; + + Ok(to) +} + #[cfg(test)] mod tests { use crate::types::{transaction::rlp_opt, U64}; diff --git a/ethers-core/src/types/transaction/request.rs b/ethers-core/src/types/transaction/request.rs index 347eaa61..2068645f 100644 --- a/ethers-core/src/types/transaction/request.rs +++ b/ethers-core/src/types/transaction/request.rs @@ -1,5 +1,5 @@ //! Transaction types -use super::{extract_chain_id, rlp_opt, NUM_TX_FIELDS}; +use super::{decode_to, extract_chain_id, rlp_opt, NUM_TX_FIELDS}; use crate::{ types::{Address, Bytes, NameOrAddress, Signature, Transaction, H256, U256, U64}, utils::keccak256, @@ -217,8 +217,7 @@ impl TransactionRequest { *offset += 1; } - txn.to = Some(rlp.at(*offset)?.as_val()?); - *offset += 1; + txn.to = decode_to(rlp, offset)?; txn.value = Some(rlp.at(*offset)?.as_val()?); *offset += 1;