1mod bounded_encoder;
2
3use std::default::Default;
4
5use crate::{
6 codec::abi_encoder::bounded_encoder::BoundedEncoder,
7 types::{errors::Result, Token},
8};
9
10#[derive(Debug, Clone, Copy)]
11pub struct EncoderConfig {
12 pub max_depth: usize,
15 pub max_tokens: usize,
18}
19
20impl Default for EncoderConfig {
22 fn default() -> Self {
23 Self {
24 max_depth: 45,
25 max_tokens: 10_000,
26 }
27 }
28}
29#[derive(Default, Clone, Debug)]
32pub struct ABIEncoder {
33 pub config: EncoderConfig,
34}
35
36impl ABIEncoder {
37 pub fn new(config: EncoderConfig) -> Self {
38 Self { config }
39 }
40
41 pub fn encode(&self, tokens: &[Token]) -> Result<Vec<u8>> {
44 BoundedEncoder::new(self.config).encode(tokens)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use std::slice;
51
52 use super::*;
53 use crate::{
54 to_named,
55 types::{
56 errors::Error,
57 param_types::{EnumVariants, ParamType},
58 StaticStringToken, U256,
59 },
60 };
61
62 #[test]
63 fn encode_multiple_uint() -> Result<()> {
64 let tokens = [
65 Token::U8(u8::MAX),
66 Token::U16(u16::MAX),
67 Token::U32(u32::MAX),
68 Token::U64(u64::MAX),
69 Token::U128(u128::MAX),
70 Token::U256(U256::MAX),
71 ];
72
73 let result = ABIEncoder::default().encode(&tokens)?;
74
75 let expected = [
76 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
81 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
83 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, ];
85
86 assert_eq!(result, expected);
87
88 Ok(())
89 }
90
91 #[test]
92 fn encode_bool() -> Result<()> {
93 let token = Token::Bool(true);
94
95 let result = ABIEncoder::default().encode(&[token])?;
96
97 let expected = [1];
98
99 assert_eq!(result, expected);
100
101 Ok(())
102 }
103
104 #[test]
105 fn encode_b256() -> Result<()> {
106 let data = [
107 213, 87, 156, 70, 223, 204, 127, 24, 32, 112, 19, 230, 91, 68, 228, 203, 78, 44, 34,
108 152, 244, 172, 69, 123, 168, 248, 39, 67, 243, 30, 147, 11,
109 ];
110 let token = Token::B256(data);
111
112 let result = ABIEncoder::default().encode(&[token])?;
113
114 assert_eq!(result, data);
115
116 Ok(())
117 }
118
119 #[test]
120 fn encode_bytes() -> Result<()> {
121 let token = Token::Bytes([255, 0, 1, 2, 3, 4, 5].to_vec());
122
123 let result = ABIEncoder::default().encode(&[token])?;
124
125 let expected = [
126 0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5, ];
129
130 assert_eq!(result, expected);
131
132 Ok(())
133 }
134
135 #[test]
136 fn encode_string() -> Result<()> {
137 let token = Token::String("This is a full sentence".to_string());
138
139 let result = ABIEncoder::default().encode(&[token])?;
140
141 let expected = [
142 0, 0, 0, 0, 0, 0, 0, 23, 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,
144 116, 101, 110, 99, 101, ];
146
147 assert_eq!(result, expected);
148
149 Ok(())
150 }
151
152 #[test]
153 fn encode_raw_slice() -> Result<()> {
154 let token = Token::RawSlice([255, 0, 1, 2, 3, 4, 5].to_vec());
155
156 let result = ABIEncoder::default().encode(&[token])?;
157
158 let expected = [
159 0, 0, 0, 0, 0, 0, 0, 7, 255, 0, 1, 2, 3, 4, 5, ];
162
163 assert_eq!(result, expected);
164
165 Ok(())
166 }
167
168 #[test]
169 fn encode_string_array() -> Result<()> {
170 let token = Token::StringArray(StaticStringToken::new(
171 "This is a full sentence".into(),
172 Some(23),
173 ));
174
175 let result = ABIEncoder::default().encode(&[token])?;
176
177 let expected = [
178 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,
179 116, 101, 110, 99, 101, ];
181
182 assert_eq!(result, expected);
183
184 Ok(())
185 }
186
187 #[test]
188 fn encode_string_slice() -> Result<()> {
189 let token = Token::StringSlice(StaticStringToken::new(
190 "This is a full sentence".into(),
191 None,
192 ));
193
194 let result = ABIEncoder::default().encode(&[token])?;
195
196 let expected = [
197 0, 0, 0, 0, 0, 0, 0, 23, 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,
199 116, 101, 110, 99, 101, ];
201
202 assert_eq!(result, expected);
203
204 Ok(())
205 }
206
207 #[test]
208 fn encode_tuple() -> Result<()> {
209 let token = Token::Tuple(vec![Token::U32(255), Token::Bool(true)]);
210
211 let result = ABIEncoder::default().encode(&[token])?;
212
213 let expected = [
214 0, 0, 0, 255, 1, ];
217
218 assert_eq!(result, expected);
219
220 Ok(())
221 }
222
223 #[test]
224 fn encode_array() -> Result<()> {
225 let token = Token::Tuple(vec![Token::U32(255), Token::U32(128)]);
226
227 let result = ABIEncoder::default().encode(&[token])?;
228
229 let expected = [
230 0, 0, 0, 255, 0, 0, 0, 128, ];
233
234 assert_eq!(result, expected);
235
236 Ok(())
237 }
238
239 #[test]
240 fn encode_enum_with_deeply_nested_types() -> Result<()> {
241 let types = to_named(&[ParamType::Bool, ParamType::StringArray(10)]);
248 let deeper_enum_variants = EnumVariants::new(types)?;
249 let deeper_enum_token =
250 Token::StringArray(StaticStringToken::new("0123456789".into(), Some(10)));
251
252 let fields = to_named(&[
260 ParamType::Enum {
261 name: "".to_string(),
262 enum_variants: deeper_enum_variants.clone(),
263 generics: vec![],
264 },
265 ParamType::Bool,
266 ]);
267 let struct_a_type = ParamType::Struct {
268 name: "".to_string(),
269 fields,
270 generics: vec![],
271 };
272
273 let struct_a_token = Token::Struct(vec![
274 Token::Enum(Box::new((1, deeper_enum_token, deeper_enum_variants))),
275 Token::U32(11332),
276 ]);
277
278 let types = to_named(&[struct_a_type, ParamType::Bool, ParamType::U64]);
287 let top_level_enum_variants = EnumVariants::new(types)?;
288 let top_level_enum_token =
289 Token::Enum(Box::new((0, struct_a_token, top_level_enum_variants)));
290
291 let result = ABIEncoder::default().encode(slice::from_ref(&top_level_enum_token))?;
292
293 let expected = [
294 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 0, 0, 44, 68, ];
299
300 assert_eq!(result, expected);
301
302 Ok(())
303 }
304
305 #[test]
306 fn encode_nested_structs() -> Result<()> {
307 let token = Token::Struct(vec![
308 Token::U16(10),
309 Token::Struct(vec![
310 Token::Bool(true),
311 Token::Array(vec![Token::U8(1), Token::U8(2)]),
312 ]),
313 ]);
314
315 let result = ABIEncoder::default().encode(&[token])?;
316
317 let expected = [
318 0, 10, 1, 1, 2, ];
322
323 assert_eq!(result, expected);
324
325 Ok(())
326 }
327
328 #[test]
329 fn encode_comprehensive() -> Result<()> {
330 let foo = Token::Struct(vec![
331 Token::U16(10),
332 Token::Struct(vec![
333 Token::Bool(true),
334 Token::Array(vec![Token::U8(1), Token::U8(2)]),
335 ]),
336 ]);
337 let arr_u8 = Token::Array(vec![Token::U8(1), Token::U8(2)]);
338 let b256 = Token::B256([255; 32]);
339 let str_arr = Token::StringArray(StaticStringToken::new(
340 "This is a full sentence".into(),
341 Some(23),
342 ));
343 let tokens = vec![foo, arr_u8, b256, str_arr];
344
345 let result = ABIEncoder::default().encode(&tokens)?;
346
347 let expected = [
348 0, 10, 1, 1, 2, 1, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 102, 117, 108, 108, 32, 115, 101, 110,
359 116, 101, 110, 99, 101, ];
361
362 assert_eq!(result, expected);
363
364 Ok(())
365 }
366
367 #[test]
368 fn enums_with_only_unit_variants_are_encoded_in_one_word() -> Result<()> {
369 let expected = [0, 0, 0, 0, 0, 0, 0, 1];
370
371 let types = to_named(&[ParamType::Unit, ParamType::Unit]);
372 let enum_selector = Box::new((1, Token::Unit, EnumVariants::new(types)?));
373
374 let actual = ABIEncoder::default().encode(&[Token::Enum(enum_selector)])?;
375
376 assert_eq!(actual, expected);
377
378 Ok(())
379 }
380
381 #[test]
382 fn vec_in_enum() -> Result<()> {
383 let types = to_named(&[ParamType::B256, ParamType::Vector(Box::new(ParamType::U64))]);
385 let variants = EnumVariants::new(types)?;
386 let selector = (1, Token::Vector(vec![Token::U64(5)]), variants);
387 let token = Token::Enum(Box::new(selector));
388
389 let result = ABIEncoder::default().encode(&[token])?;
391
392 let expected = [
394 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, ];
397
398 assert_eq!(result, expected);
399
400 Ok(())
401 }
402
403 #[test]
404 fn enum_in_vec() -> Result<()> {
405 let types = to_named(&[ParamType::B256, ParamType::U8]);
407 let variants = EnumVariants::new(types)?;
408 let selector = (1, Token::U8(8), variants);
409 let enum_token = Token::Enum(Box::new(selector));
410
411 let vec_token = Token::Vector(vec![enum_token]);
412
413 let result = ABIEncoder::default().encode(&[vec_token])?;
415
416 let expected = [
418 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 8, ];
421
422 assert_eq!(result, expected);
423
424 Ok(())
425 }
426
427 #[test]
428 fn vec_in_struct() -> Result<()> {
429 let token = Token::Struct(vec![Token::Vector(vec![Token::U64(5)]), Token::U8(9)]);
431
432 let result = ABIEncoder::default().encode(&[token])?;
434
435 let expected = [
437 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 5, 9, ];
440
441 assert_eq!(result, expected);
442
443 Ok(())
444 }
445
446 #[test]
447 fn vec_in_vec() -> Result<()> {
448 let token = Token::Vector(vec![Token::Vector(vec![Token::U8(5), Token::U8(6)])]);
450
451 let result = ABIEncoder::default().encode(&[token])?;
453
454 let expected = [
456 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 5, 6, ];
459
460 assert_eq!(result, expected);
461
462 Ok(())
463 }
464
465 #[test]
466 fn max_depth_surpassed() {
467 const MAX_DEPTH: usize = 2;
468 let config = EncoderConfig {
469 max_depth: MAX_DEPTH,
470 ..Default::default()
471 };
472 let msg = "depth limit `2` reached while encoding. Try increasing it".to_string();
473
474 [nested_struct, nested_enum, nested_tuple, nested_array]
475 .iter()
476 .map(|fun| fun(MAX_DEPTH + 1))
477 .for_each(|token| {
478 assert_encoding_failed(config, token, &msg);
479 });
480 }
481
482 fn assert_encoding_failed(config: EncoderConfig, token: Token, msg: &str) {
483 let encoder = ABIEncoder::new(config);
484
485 let err = encoder.encode(&[token]);
486
487 let Err(Error::Codec(actual_msg)) = err else {
488 panic!("expected a Codec error. Got: `{err:?}`");
489 };
490 assert_eq!(actual_msg, msg);
491 }
492
493 fn nested_struct(depth: usize) -> Token {
494 let fields = if depth == 1 {
495 vec![Token::U8(255), Token::String("bloopblip".to_string())]
496 } else {
497 vec![nested_struct(depth - 1)]
498 };
499
500 Token::Struct(fields)
501 }
502
503 fn nested_enum(depth: usize) -> Token {
504 if depth == 0 {
505 return Token::U8(255);
506 }
507
508 let inner_enum = nested_enum(depth - 1);
509
510 let selector = (
513 0u64,
514 inner_enum,
515 EnumVariants::new(to_named(&[ParamType::U64])).unwrap(),
516 );
517
518 Token::Enum(Box::new(selector))
519 }
520
521 fn nested_array(depth: usize) -> Token {
522 if depth == 1 {
523 Token::Array(vec![Token::U8(255)])
524 } else {
525 Token::Array(vec![nested_array(depth - 1)])
526 }
527 }
528
529 fn nested_tuple(depth: usize) -> Token {
530 let fields = if depth == 1 {
531 vec![Token::U8(255), Token::String("bloopblip".to_string())]
532 } else {
533 vec![nested_tuple(depth - 1)]
534 };
535
536 Token::Tuple(fields)
537 }
538}