ethers_core/abi/
packed.rs1use ethabi::Token;
2use thiserror::Error;
3use Token::*;
4
5#[derive(Debug, Error)]
7pub enum EncodePackedError {
8 #[error("This token cannot be encoded in packed mode: {0:?}")]
9 InvalidToken(Token),
10
11 #[error("FixedBytes token length > 32")]
12 InvalidBytesLength,
13}
14
15pub fn encode_packed(tokens: &[Token]) -> Result<Vec<u8>, EncodePackedError> {
55 let mut max = 0;
57 for token in tokens {
58 check(token)?;
59 max += max_encoded_length(token);
60 }
61
62 let mut bytes = Vec::with_capacity(max);
64 for token in tokens {
65 encode_token(token, &mut bytes, false);
66 }
67 Ok(bytes)
68}
69
70fn max_encoded_length(token: &Token) -> usize {
72 match token {
73 Int(_) | Uint(_) | FixedBytes(_) => 32,
74 Address(_) => 20,
75 Bool(_) => 1,
76 Array(vec) | FixedArray(vec) | Tuple(vec) => {
78 vec.iter().map(|token| max_encoded_length(token).max(32)).sum()
79 }
80 Bytes(b) => b.len(),
81 String(s) => s.len(),
82 }
83}
84
85fn check(token: &Token) -> Result<(), EncodePackedError> {
87 match token {
88 FixedBytes(vec) if vec.len() > 32 => Err(EncodePackedError::InvalidBytesLength),
89
90 Tuple(_) => Err(EncodePackedError::InvalidToken(token.clone())),
91 Array(vec) | FixedArray(vec) => {
92 for t in vec.iter() {
93 if t.is_dynamic() || matches!(t, Array(_)) {
94 return Err(EncodePackedError::InvalidToken(token.clone()))
95 }
96 check(t)?;
97 }
98 Ok(())
99 }
100
101 _ => Ok(()),
102 }
103}
104
105fn encode_token(token: &Token, out: &mut Vec<u8>, in_array: bool) {
107 match token {
108 Address(addr) => {
110 if in_array {
111 out.extend_from_slice(&[0; 12]);
112 }
113 out.extend_from_slice(&addr.0)
114 }
115 Int(n) | Uint(n) => {
116 let mut buf = [0; 32];
117 n.to_big_endian(&mut buf);
118 let start = if in_array { 0 } else { 32 - ((n.bits() + 7) / 8) };
119 out.extend_from_slice(&buf[start..32]);
120 }
121 Bool(b) => {
122 if in_array {
123 out.extend_from_slice(&[0; 31]);
124 }
125 out.push((*b) as u8);
126 }
127 FixedBytes(bytes) => {
128 out.extend_from_slice(bytes);
129 if in_array {
130 let mut remaining = vec![0; 32 - bytes.len()];
131 out.append(&mut remaining);
132 }
133 }
134
135 Bytes(bytes) => out.extend_from_slice(bytes),
137 String(s) => out.extend_from_slice(s.as_bytes()),
138 Array(vec) | FixedArray(vec) => {
139 for token in vec {
140 encode_token(token, out, true);
141 }
142 }
143
144 token => unreachable!("Uncaught invalid token: {token:?}"),
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152 use hex_literal::hex;
153
154 fn encode(tokens: &[Token]) -> Vec<u8> {
155 encode_packed(tokens).unwrap()
156 }
157
158 fn string(s: &str) -> Token {
159 Token::String(s.into())
160 }
161
162 fn bytes(b: &[u8]) -> Token {
163 Token::Bytes(b.into())
164 }
165
166 #[test]
167 fn encode_bytes0() {
168 let expected = b"hello world";
169 assert_eq!(encode_packed(&[string("hello world")]).unwrap(), expected);
170 assert_eq!(encode_packed(&[bytes(b"hello world")]).unwrap(), expected);
171 assert_eq!(
172 encode_packed(&[string("hello"), string(" "), string("world")]).unwrap(),
173 expected
174 );
175 assert_eq!(
176 encode_packed(&[bytes(b"hello"), bytes(b" "), bytes(b"world")]).unwrap(),
177 expected
178 );
179 }
180
181 #[test]
185 fn encode_address() {
186 let address = Token::Address([0x11u8; 20].into());
187 let encoded = encode(&[address]);
188 let expected = hex!("1111111111111111111111111111111111111111");
189 assert_eq!(encoded, expected);
190 }
191
192 #[test]
193 fn encode_dynamic_array_of_addresses() {
194 let address1 = Token::Address([0x11u8; 20].into());
195 let address2 = Token::Address([0x22u8; 20].into());
196 let addresses = Token::Array(vec![address1, address2]);
197 let encoded = encode(&[addresses]);
198 let expected = hex!(
199 "
200 0000000000000000000000001111111111111111111111111111111111111111
201 0000000000000000000000002222222222222222222222222222222222222222
202 "
203 )
204 .to_vec();
205 assert_eq!(encoded, expected);
206 }
207
208 #[test]
209 fn encode_fixed_array_of_addresses() {
210 let address1 = Token::Address([0x11u8; 20].into());
211 let address2 = Token::Address([0x22u8; 20].into());
212 let addresses = Token::FixedArray(vec![address1, address2]);
213 let encoded = encode(&[addresses]);
214 let expected = hex!(
215 "
216 0000000000000000000000001111111111111111111111111111111111111111
217 0000000000000000000000002222222222222222222222222222222222222222
218 "
219 )
220 .to_vec();
221 assert_eq!(encoded, expected);
222 }
223
224 #[test]
225 fn encode_two_addresses() {
226 let address1 = Token::Address([0x11u8; 20].into());
227 let address2 = Token::Address([0x22u8; 20].into());
228 let encoded = encode(&[address1, address2]);
229 let expected = hex!(
230 "
231 1111111111111111111111111111111111111111
232 2222222222222222222222222222222222222222
233 "
234 )
235 .to_vec();
236 assert_eq!(encoded, expected);
237 }
238
239 #[test]
240 fn encode_empty_array() {
241 let encoded = encode(&[Token::Array(vec![]), Token::Array(vec![])]);
242 assert_eq!(encoded, b"");
243 }
244
245 #[test]
246 fn encode_bytes() {
247 let bytes = Token::Bytes(hex!("1234").to_vec());
248 let encoded = encode(&[bytes]);
249 let expected = hex!("1234");
250 assert_eq!(encoded, expected);
251 }
252
253 #[test]
254 fn encode_bytes2() {
255 let bytes = Token::Bytes(
256 hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec(),
257 );
258 let encoded = encode(&[bytes]);
259 let expected =
260 hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec();
261 assert_eq!(encoded, expected);
262 }
263
264 #[test]
265 fn encode_bytes3() {
266 let bytes = Token::Bytes(
267 hex!(
268 "
269 1000000000000000000000000000000000000000000000000000000000000000
270 1000000000000000000000000000000000000000000000000000000000000000
271 "
272 )
273 .to_vec(),
274 );
275 let encoded = encode(&[bytes]);
276 let expected = hex!(
277 "
278 1000000000000000000000000000000000000000000000000000000000000000
279 1000000000000000000000000000000000000000000000000000000000000000
280 "
281 )
282 .to_vec();
283 assert_eq!(encoded, expected);
284 }
285
286 #[test]
287 fn encode_string() {
288 let s = Token::String("gavofyork".to_owned());
289 let encoded = encode(&[s]);
290 assert_eq!(encoded, b"gavofyork");
291 }
292
293 #[test]
294 fn encode_two_bytes() {
295 let bytes1 = Token::Bytes(
296 hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec(),
297 );
298 let bytes2 = Token::Bytes(
299 hex!("0010000000000000000000000000000000000000000000000000000000000002").to_vec(),
300 );
301 let encoded = encode(&[bytes1, bytes2]);
302 let expected = hex!(
303 "
304 10000000000000000000000000000000000000000000000000000000000002
305 0010000000000000000000000000000000000000000000000000000000000002
306 "
307 )
308 .to_vec();
309 assert_eq!(encoded, expected);
310 }
311
312 #[test]
313 fn encode_fixed_bytes() {
314 let bytes = Token::FixedBytes(vec![0x12, 0x34]);
315 let encoded = encode(&[bytes]);
316 let expected = hex!("1234");
317 assert_eq!(encoded, expected);
318 }
319
320 #[test]
321 fn encode_array_of_fixed_bytes() {
322 let array = Token::FixedArray(vec![
323 Token::FixedBytes(vec![0x12, 0x34]),
324 Token::FixedBytes(vec![0x56, 0x78]),
325 ]);
326 let encoded = encode(&[array]);
327 let expected = hex!(
328 "
329 1234000000000000000000000000000000000000000000000000000000000000
330 5678000000000000000000000000000000000000000000000000000000000000
331 "
332 );
333 assert_eq!(encoded, expected);
334 }
335
336 #[test]
337 fn encode_uint() {
338 let mut uint = [0u8; 32];
339 uint[31] = 4;
340 let encoded = encode(&[Token::Uint(uint.into())]);
341 let expected = hex!("04");
342 assert_eq!(encoded, expected);
343 }
344
345 #[test]
346 fn encode_int() {
347 let mut int = [0u8; 32];
348 int[31] = 4;
349 let encoded = encode(&[Token::Int(int.into())]);
350 let expected = hex!("04");
351 assert_eq!(encoded, expected);
352 }
353
354 #[test]
355 fn encode_bool() {
356 let encoded = encode(&[Token::Bool(true)]);
357 let expected = hex!("01");
358 assert_eq!(encoded, expected);
359 }
360
361 #[test]
362 fn encode_bool2() {
363 let encoded = encode(&[Token::Bool(false)]);
364 let expected = hex!("00");
365 assert_eq!(encoded, expected);
366 }
367
368 #[test]
369 fn comprehensive_test() {
370 let bytes = hex!(
371 "
372 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
373 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
374 "
375 )
376 .to_vec();
377 let encoded = encode(&[
378 Token::Int(5.into()),
379 Token::Bytes(bytes.clone()),
380 Token::Int(3.into()),
381 Token::Bytes(bytes),
382 ]);
383
384 let expected = hex!(
385 "
386 05
387 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
388 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
389 03
390 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
391 131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
392 "
393 )
394 .to_vec();
395 assert_eq!(encoded, expected);
396 }
397
398 #[test]
399 fn comprehensive_test2() {
400 let encoded = encode(&vec![
401 Token::Int(1.into()),
402 Token::String("gavofyork".to_owned()),
403 Token::Int(2.into()),
404 Token::Int(3.into()),
405 Token::Int(4.into()),
406 Token::Array(vec![Token::Int(5.into()), Token::Int(6.into()), Token::Int(7.into())]),
407 ]);
408
409 let expected = hex!(
410 "
411 01
412 6761766f66796f726b
413 02
414 03
415 04
416 0000000000000000000000000000000000000000000000000000000000000005
417 0000000000000000000000000000000000000000000000000000000000000006
418 0000000000000000000000000000000000000000000000000000000000000007
419 "
420 )
421 .to_vec();
422 assert_eq!(encoded, expected);
423 }
424}