kona_protocol/batch/tx_data/
eip1559.rs

1//! This module contains the eip1559 transaction data type for a span batch.
2
3use crate::{SpanBatchError, SpanDecodingError};
4use alloy_consensus::{SignableTransaction, Signed, TxEip1559};
5use alloy_eips::eip2930::AccessList;
6use alloy_primitives::{Address, Signature, TxKind, U256};
7use alloy_rlp::{Bytes, RlpDecodable, RlpEncodable};
8
9/// The transaction data for an EIP-1559 transaction within a span batch.
10#[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)]
11pub struct SpanBatchEip1559TransactionData {
12    /// The ETH value of the transaction.
13    pub value: U256,
14    /// Maximum priority fee per gas.
15    pub max_priority_fee_per_gas: U256,
16    /// Maximum fee per gas.
17    pub max_fee_per_gas: U256,
18    /// Transaction calldata.
19    pub data: Bytes,
20    /// Access list, used to pre-warm storage slots through static declaration.
21    pub access_list: AccessList,
22}
23
24impl SpanBatchEip1559TransactionData {
25    /// Converts [`SpanBatchEip1559TransactionData`] into a signed [`TxEip1559`].
26    pub fn to_signed_tx(
27        &self,
28        nonce: u64,
29        gas: u64,
30        to: Option<Address>,
31        chain_id: u64,
32        signature: Signature,
33    ) -> Result<Signed<TxEip1559>, SpanBatchError> {
34        let eip1559_tx = TxEip1559 {
35            chain_id,
36            nonce,
37            max_fee_per_gas: u128::from_be_bytes(
38                self.max_fee_per_gas.to_be_bytes::<32>()[16..].try_into().map_err(|_| {
39                    SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData)
40                })?,
41            ),
42            max_priority_fee_per_gas: u128::from_be_bytes(
43                self.max_priority_fee_per_gas.to_be_bytes::<32>()[16..].try_into().map_err(
44                    |_| SpanBatchError::Decoding(SpanDecodingError::InvalidTransactionData),
45                )?,
46            ),
47            gas_limit: gas,
48            to: to.map_or(TxKind::Create, TxKind::Call),
49            value: self.value,
50            input: self.data.clone().into(),
51            access_list: self.access_list.clone(),
52        };
53        let signature_hash = eip1559_tx.signature_hash();
54        Ok(Signed::new_unchecked(eip1559_tx, signature, signature_hash))
55    }
56}
57
58#[cfg(test)]
59mod test {
60    use super::*;
61    use crate::SpanBatchTransactionData;
62    use alloc::vec::Vec;
63    use alloy_rlp::{Decodable, Encodable};
64
65    #[test]
66    fn encode_eip1559_tx_data_roundtrip() {
67        let variable_fee_tx = SpanBatchEip1559TransactionData {
68            value: U256::from(0xFF),
69            max_fee_per_gas: U256::from(0xEE),
70            max_priority_fee_per_gas: U256::from(0xDD),
71            data: Bytes::from(alloc::vec![0x01, 0x02, 0x03]),
72            access_list: AccessList::default(),
73        };
74        let mut encoded_buf = Vec::new();
75        SpanBatchTransactionData::Eip1559(variable_fee_tx.clone()).encode(&mut encoded_buf);
76
77        let decoded = SpanBatchTransactionData::decode(&mut encoded_buf.as_slice()).unwrap();
78        let SpanBatchTransactionData::Eip1559(variable_fee_decoded) = decoded else {
79            panic!("Expected SpanBatchEip1559TransactionData, got {:?}", decoded);
80        };
81
82        assert_eq!(variable_fee_tx, variable_fee_decoded);
83    }
84}