eest_types/blockchain/
transaction.rs

1use crate::{utils::deserializer::deserialize_maybe_empty, TestAuthorization};
2use cfx_rpc_primitives::Bytes;
3use cfx_types::{Address, H256, U256, U64};
4use primitives::transaction::AccessList;
5use serde::Deserialize;
6
7#[derive(Debug, PartialEq, Eq, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct Transaction {
10    #[serde(default, rename = "type")]
11    pub tx_type: U64,
12    pub chain_id: Option<U256>,
13    pub nonce: U256,
14    pub gas_price: Option<U256>,
15    pub max_priority_fee_per_gas: Option<U256>,
16    pub max_fee_per_gas: Option<U256>,
17    pub gas_limit: U256,
18    #[serde(default, deserialize_with = "deserialize_maybe_empty")]
19    pub to: Option<Address>,
20    pub value: U256,
21    pub data: Bytes,
22    pub v: U64,
23    pub r: U256,
24    pub s: U256,
25    pub sender: Option<Address>,
26    pub secret_key: Option<H256>,
27    pub access_list: Option<AccessList>,
28    pub max_fee_per_blob_gas: Option<U256>,
29    pub blob_versioned_hashes: Option<Vec<H256>>,
30    pub authorization_list: Option<Vec<TestAuthorization>>,
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36
37    #[test]
38    fn recover_basic() {
39        let json_str = r#"{
40            "type": "0x00",
41            "chainId": "0x01",
42            "nonce": "0x00",
43            "gasPrice": "0x0a",
44            "gasLimit": "0x07a120",
45            "to": "0x0000000000000000000000000000000000001000",
46            "value": "0x00",
47            "data": "0x00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002003fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2efffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
48            "v": "0x26",
49            "r": "0xb71d8dd5ac327ec1b822930c066a9d0931a26f8529cbd0dca51a6a1f3fc508c9",
50            "s": "0x63698823fb964779539d8fd4d016e7326cbd9dab987233458980d422776167b5",
51            "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"
52        }"#;
53
54        let tx: Transaction = serde_json::from_str(json_str).unwrap();
55        assert_eq!(tx.tx_type, U64::from(0));
56        assert_eq!(tx.chain_id, Some(U256::from(1)));
57        assert_eq!(tx.nonce, U256::from(0));
58        assert_eq!(tx.v, U64::from(38));
59        assert_eq!(tx.access_list, None);
60    }
61
62    #[test]
63    fn recover_access_list_tx() {
64        let json_str = r#"{
65            "type": "0x01",
66            "chainId": "0x01",
67            "nonce": "0x00",
68            "gasPrice": "0x07",
69            "gasLimit": "0x04ef00",
70            "to": "0x0000000000000000000000000000000000001000",
71            "value": "0x01",
72            "data": "0x",
73            "accessList": [
74                {
75                    "address": "0x0000000000000000000000000000000000000000",
76                    "storageKeys": [
77                        "0x0000000000000000000000000000000000000000000000000000000000000000"
78                    ]
79                }
80            ],
81            "v": "0x00",
82            "r": "0x81a25ffdb3797e6428f854c642e1884ee7b7be0c4ccbb7e989b70039b87e4450",
83            "s": "0x2d25e40f45271d5f77735d06550dff43bf328190de034157cefec446855513d6",
84            "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"
85        }"#;
86
87        let tx: Transaction = serde_json::from_str(json_str).unwrap();
88        assert_eq!(tx.tx_type, U64::from(1));
89        assert!(tx.access_list.is_some());
90        assert_eq!(tx.access_list.unwrap().len(), 1);
91    }
92
93    #[test]
94    fn recover_1559_tx() {
95        let json_str = r#"{
96            "type": "0x02",
97            "chainId": "0x01",
98            "nonce": "0x00",
99            "maxPriorityFeePerGas": "0x00",
100            "maxFeePerGas": "0x07",
101            "gasLimit": "0x0f4240",
102            "to": "0x0000000000000000000000000000000000001000",
103            "value": "0x00",
104            "data": "0x000000000000000000000000000000000000000000000000000000000000000c",
105            "accessList": [],
106            "v": "0x00",
107            "r": "0x0250e37fb1094dca850d5e9930a67cfcbdfb10dd4e93d576c1add47ebcaa9087",
108            "s": "0x77e2484f633730a17870768524826e03dbb3a1856b5b07b850631453167b42c5",
109            "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"
110        }"#;
111
112        let tx: Transaction = serde_json::from_str(json_str).unwrap();
113        assert_eq!(tx.tx_type, U64::from(2));
114        assert_eq!(tx.max_fee_per_gas, Some(U256::from(7)));
115    }
116
117    #[test]
118    fn recover_7702_tx() {
119        let json_str = r#"{
120            "type": "0x04",
121            "chainId": "0x01",
122            "nonce": "0x00",
123            "maxPriorityFeePerGas": "0x00",
124            "maxFeePerGas": "0x07",
125            "gasLimit": "0x023a5a",
126            "to": "0x0000000000000000000000000000000000001000",
127            "value": "0x00",
128            "data": "0x010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010100",
129            "accessList": [],
130            "v": "0x01",
131            "r": "0x3f1b651968d0fb5693206b5f7ece4b4194828417e03abc35f99657e3a39bf485",
132            "s": "0x69b6b8c3bc51916a47bffe07298daf32177f39cc14e1d043c55d46ebca4e67b8",
133            "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
134            "authorizationList": [
135                {
136                    "chainId": "0x00",
137                    "address": "0x0000000000000000000000000000000000000001",
138                    "nonce": "0x00",
139                    "v": "0x00",
140                    "r": "0x33a629f82b5aaff5b4bfe6b9ab53bb3646b92cda403d7c834f72c9a5073aec20",
141                    "s": "0x16902e4a3c089e05d649cab6bd74b6f424fae0eefad3a4944fa452ff7413b5d3",
142                    "signer": "0x8a0a19589531694250d570040a0c4b74576919b8",
143                    "yParity": "0x00"
144                }
145            ]
146        }"#;
147
148        let tx: Transaction = serde_json::from_str(json_str).unwrap();
149        assert_eq!(tx.tx_type, U64::from(4));
150        assert!(tx.authorization_list.is_some());
151        assert_eq!(tx.authorization_list.unwrap().len(), 1);
152    }
153
154    #[test]
155    fn recover_4844_tx() {
156        let json_str = r#"{
157            "type": "0x03",
158            "chainId": "0x01",
159            "nonce": "0x00",
160            "maxPriorityFeePerGas": "0x00",
161            "maxFeePerGas": "0x07",
162            "gasLimit": "0x0f4240",
163            "to": "0x000f3df6d732807ef1319fb7b8bb8522d0beac02",
164            "value": "0x00",
165            "data": "0x000000000000000000000000000000000000000000000000000000000000000c",
166            "accessList": [],
167            "maxFeePerBlobGas": "0x01",
168            "blobVersionedHashes": [
169                "0x0100000000000000000000000000000000000000000000000000000000000000"
170            ],
171            "v": "0x01",
172            "r": "0x53116c986dc393633b36cacf6e2c5cf896531ffed002ba696a1bab16db1ef4f4",
173            "s": "0x45d8f72ef3b93897c58143b6b4368c56947344b2770695dccc26aa6d2f35b248",
174            "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"
175        }"#;
176
177        let tx: Transaction = serde_json::from_str(json_str).unwrap();
178        assert_eq!(tx.tx_type, U64::from(3));
179        assert!(tx.blob_versioned_hashes.is_some());
180        assert_eq!(tx.blob_versioned_hashes.unwrap().len(), 1);
181        assert_eq!(tx.max_fee_per_blob_gas, Some(U256::from(1)));
182    }
183}