alloy_zksync/network/unsigned_tx/eip712/
meta.rs1use alloy::primitives::{Address, Bytes, FixedBytes, U256};
2use alloy::rlp::{Decodable, Encodable, Header};
3use serde::{Deserialize, Serialize, ser::SerializeSeq};
4
5use super::utils::{BytecodeHashError, hash_bytecode};
6
7fn serialize_bytes<S: serde::Serializer>(
9 bytes: &Vec<Bytes>,
10 serializer: S,
11) -> Result<S::Ok, S::Error> {
12 let mut seq = serializer.serialize_seq(Some(bytes.len()))?;
13 for e in bytes {
14 seq.serialize_element(&e.0)?;
15 }
16 seq.end()
17}
18
19fn serialize_bytes_custom<S: serde::Serializer>(
21 bytes: &Bytes,
22 serializer: S,
23) -> Result<S::Ok, S::Error> {
24 serializer.serialize_bytes(&bytes.0)
25}
26
27fn serialize_bytes_opt<S: serde::Serializer>(
28 value: &Option<Bytes>,
29 serializer: S,
30) -> Result<S::Ok, S::Error> {
31 match value {
32 Some(bytes) => serializer.serialize_bytes(&bytes.0),
33 None => serializer.serialize_none(),
34 }
35}
36#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Debug, Eq, Hash)]
43#[serde(rename_all = "camelCase")]
44pub struct Eip712Meta {
45 pub gas_per_pubdata: U256,
47 #[serde(default)]
52 #[serde(serialize_with = "serialize_bytes")]
53 pub factory_deps: Vec<Bytes>,
54 #[serde(serialize_with = "serialize_bytes_opt")]
58 pub custom_signature: Option<Bytes>,
59 pub paymaster_params: Option<PaymasterParams>,
61}
62
63impl Eip712Meta {
64 pub fn factory_deps_hashes(&self) -> Result<Vec<FixedBytes<32>>, BytecodeHashError> {
68 let mut hashes = Vec::with_capacity(self.factory_deps.len() * 32);
69 for dep in &self.factory_deps {
70 let hash = hash_bytecode(dep)?;
71 hashes.push(hash.into());
72 }
73 Ok(hashes)
74 }
75}
76
77impl Decodable for Eip712Meta {
78 fn decode(buf: &mut &[u8]) -> alloy::rlp::Result<Self> {
79 fn opt_decode<T: Decodable>(buf: &mut &[u8]) -> alloy::rlp::Result<Option<T>> {
80 Ok(Decodable::decode(buf).ok()) }
82
83 let gas_per_pubdata = Decodable::decode(buf)?;
84 let factory_deps = Decodable::decode(buf)?;
85 let custom_signature = opt_decode(buf)?;
86 let paymaster_params = opt_decode(buf)?;
87
88 Ok(Self {
89 gas_per_pubdata,
90 factory_deps,
91 custom_signature,
92 paymaster_params,
93 })
94 }
95}
96
97impl Encodable for Eip712Meta {
98 fn encode(&self, out: &mut dyn alloy::rlp::BufMut) {
99 fn opt_encode<T>(stream: &mut dyn alloy::rlp::BufMut, value: Option<T>)
100 where
101 T: Encodable,
102 {
103 if let Some(v) = value {
104 v.encode(stream);
105 } else {
106 "".encode(stream);
107 }
108 }
109 self.gas_per_pubdata.encode(out);
110 self.factory_deps.encode(out);
111 opt_encode(out, self.custom_signature.clone());
112 opt_encode(out, self.paymaster_params.clone());
113 }
114
115 }
117
118#[derive(Default, Serialize, Deserialize, Clone, PartialEq, Debug, Eq, Hash)]
120#[serde(rename_all = "camelCase")]
121pub struct PaymasterParams {
122 pub paymaster: Address,
124 #[serde(serialize_with = "serialize_bytes_custom")]
127 pub paymaster_input: Bytes,
128}
129
130impl Decodable for PaymasterParams {
131 fn decode(buf: &mut &[u8]) -> alloy::rlp::Result<Self> {
132 let mut bytes = Header::decode_bytes(buf, true)?;
133 let payload_view = &mut bytes;
134 Ok(Self {
135 paymaster: dbg!(Decodable::decode(payload_view))?,
136 paymaster_input: dbg!(Decodable::decode(payload_view))?,
137 })
138 }
139}
140
141impl Encodable for PaymasterParams {
142 fn encode(&self, out: &mut dyn alloy::rlp::BufMut) {
143 let h = Header {
145 list: true,
146 payload_length: self.paymaster.length() + self.paymaster_input.length(),
147 };
148 h.encode(out);
149 self.paymaster.encode(out);
150 self.paymaster_input.encode(out);
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157 use alloy::primitives::address;
158 use serde_json::json;
159
160 #[test]
161 fn test_bytes_get_serialized_into_vec() {
162 let meta = Eip712Meta {
163 gas_per_pubdata: U256::from(4),
164 factory_deps: vec![vec![1, 2].into()],
165 custom_signature: Some(vec![3, 4].into()),
166 paymaster_params: Some(PaymasterParams {
167 paymaster: address!("99E12239CBf8112fBB3f7Fd473d0558031abcbb5"),
168 paymaster_input: vec![5, 6].into(),
169 }),
170 };
171
172 let expected_json = json!({
173 "gasPerPubdata": "0x4",
174 "factoryDeps": [[1,2]],
175 "customSignature": [3, 4],
176 "paymasterParams": {
177 "paymaster": "0x99e12239cbf8112fbb3f7fd473d0558031abcbb5",
178 "paymasterInput": [5, 6],
179 }
180 });
181
182 let actual_json = serde_json::to_value(&meta).unwrap();
183 assert_eq!(expected_json, actual_json);
184 }
185}