1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use rlp::RlpStream;
use serde::{Deserialize, Serialize};
use web3::{signing::{self, Signature}, types::{SignedTransaction, CallRequest}};
pub type Result = web3::Result;
pub type U256 = web3::types::U256;
pub type U128 = web3::types::U128;
pub type U64 = web3::types::U64;
pub type H160 = web3::types::H160;
pub type H256 = web3::types::H256;
pub type Bytes = web3::types::Bytes;
pub type Options = web3::contract::Options;
pub type Transaction = web3::types::Transaction;
pub type TransactionReceipt = web3::types::TransactionReceipt;
pub type TransactionLog = web3::types::Log;
pub type BlockWithHash = web3::types::Block<H256>;
pub type BlockWithTx = web3::types::Block<Transaction>;
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct TransactionParameters {
#[serde(rename="type")]
pub tx_type: U256,
pub nonce: U256,
pub to: Option<H160>,
pub gas: U256,
#[serde(rename="gasPrice")]
pub gas_price: U256,
pub value: U256,
pub data: Bytes,
pub chain_id: u64,
}
impl TransactionParameters {
pub fn new(
chain_id: u64,
nonce: U256,
to: Option<H160>,
gas: U256,
gas_price: U256,
value: U256,
data: Bytes,
) -> TransactionParameters {
Self {
nonce,
to,
gas,
gas_price,
value,
data,
chain_id,
tx_type: U256::from(0)
}
}
pub fn to_call_request(&self) -> CallRequest {
CallRequest {
from: None,
to: self.to,
gas: None,
gas_price: Some(self.gas_price),
value: Some(self.value),
data: Some(self.data.clone()),
transaction_type: None,
access_list: None,
max_fee_per_gas: None,
max_priority_fee_per_gas: None,
}
}
fn rlp_append_legacy(&self, stream: &mut RlpStream) {
stream.append(&self.tx_type);
stream.append(&self.nonce);
stream.append(&self.gas_price);
stream.append(&self.gas);
if let Some(to) = self.to {
stream.append(&to);
} else {
stream.append(&"");
}
stream.append(&self.value);
stream.append(&self.data.0);
}
fn rlp_append_signature(&self, stream: &mut RlpStream, signature: &Signature) {
stream.append(&signature.v);
stream.append(&U256::from_big_endian(signature.r.as_bytes()));
stream.append(&U256::from_big_endian(signature.s.as_bytes()));
}
fn encode(&self, chain_id: u64, signature: Option<&Signature>) -> RlpStream {
let mut stream = RlpStream::new();
stream.begin_list(10);
self.rlp_append_legacy(&mut stream);
if let Some(signature) = signature {
self.rlp_append_signature(&mut stream, signature);
} else {
stream.append(&chain_id);
stream.append(&0u8);
stream.append(&0u8);
}
stream
}
pub fn sign(&self, sign: impl signing::Key) -> SignedTransaction {
let encoded = self.encode(self.chain_id, None).out().to_vec();
let hash = signing::keccak256(encoded.as_ref());
let signature = sign.sign(&hash, Some(self.chain_id)).expect("hash is non-zero 32-bytes; qed");
let signed = self.encode(self.chain_id, Some(&signature)).out().to_vec();
let transaction_hash = signing::keccak256(signed.as_ref()).into();
SignedTransaction {
message_hash: hash.into(),
v: signature.v,
r: signature.r,
s: signature.s,
raw_transaction: signed.into(),
transaction_hash,
}
}
}