alloy_sol_types/abi/
encoder.rs

1// Copyright 2015-2020 Parity Technologies
2// Copyright 2023-2023 Alloy Contributors
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use crate::{
11    Word,
12    abi::{Token, TokenSeq},
13    utils,
14};
15use alloc::vec::Vec;
16use core::{mem, ptr};
17
18/// An ABI encoder.
19///
20/// This is not intended for public consumption. It should be used only by the
21/// token types. If you have found yourself here, you probably want to use the
22/// high-level [`crate::SolType`] interface (or its dynamic equivalent) instead.
23#[derive(Clone, Debug, Default)]
24pub struct Encoder {
25    buf: Vec<Word>,
26    suffix_offset: Vec<usize>,
27}
28
29impl Encoder {
30    /// Instantiate a new empty encoder.
31    #[inline]
32    pub const fn new() -> Self {
33        Self { buf: Vec::new(), suffix_offset: Vec::new() }
34    }
35
36    /// Instantiate a new encoder with a given capacity in words.
37    #[inline]
38    pub fn with_capacity(size: usize) -> Self {
39        Self {
40            buf: Vec::with_capacity(size),
41            // Note: this has to be non-zero even if it won't get used. The compiler will optimize
42            // it out, but it won't for `Vec::new` (??).
43            suffix_offset: Vec::with_capacity(4),
44        }
45    }
46
47    /// Return a reference to the encoded words.
48    #[inline]
49    pub fn words(&self) -> &[Word] {
50        &self.buf
51    }
52
53    /// Finish the encoding process, returning the encoded words.
54    ///
55    /// Use `into_bytes` instead to flatten the words into bytes.
56    // https://github.com/rust-lang/rust-clippy/issues/4979
57    #[allow(clippy::missing_const_for_fn)]
58    #[inline]
59    pub fn finish(self) -> Vec<Word> {
60        self.buf
61    }
62
63    /// Return a reference to the encoded bytes.
64    #[inline]
65    pub fn bytes(&self) -> &[u8] {
66        // SAFETY: `#[repr(transparent)] FixedBytes<N>([u8; N])`
67        unsafe { &*(self.words() as *const [Word] as *const [[u8; 32]]) }.as_flattened()
68    }
69
70    /// Finish the encoding process, returning the encoded bytes.
71    #[inline]
72    pub fn into_bytes(self) -> Vec<u8> {
73        // SAFETY: `#[repr(transparent)] FixedBytes<N>([u8; N])`
74        unsafe { mem::transmute::<Vec<Word>, Vec<[u8; 32]>>(self.finish()) }.into_flattened()
75    }
76
77    /// Determine the current suffix offset.
78    ///
79    /// # Panics
80    ///
81    /// Panics if there is no current suffix offset.
82    #[inline]
83    #[cfg_attr(debug_assertions, track_caller)]
84    pub fn suffix_offset(&self) -> usize {
85        debug_assert!(!self.suffix_offset.is_empty());
86        unsafe { *self.suffix_offset.last().unwrap_unchecked() }
87    }
88
89    /// Appends a suffix offset.
90    #[inline]
91    pub fn push_offset(&mut self, words: usize) {
92        self.suffix_offset.push(words * 32);
93    }
94
95    /// Removes the last offset and returns it.
96    #[inline]
97    pub fn pop_offset(&mut self) -> Option<usize> {
98        self.suffix_offset.pop()
99    }
100
101    /// Bump the suffix offset by a given number of words.
102    #[inline]
103    pub fn bump_offset(&mut self, words: usize) {
104        if let Some(last) = self.suffix_offset.last_mut() {
105            *last += words * 32;
106        }
107    }
108
109    /// Append a word to the encoder.
110    #[inline]
111    pub fn append_word(&mut self, word: Word) {
112        self.buf.push(word);
113    }
114
115    /// Append a pointer to the current suffix offset.
116    ///
117    /// # Panics
118    ///
119    /// Panics if there is no current suffix offset.
120    #[inline]
121    #[cfg_attr(debug_assertions, track_caller)]
122    pub fn append_indirection(&mut self) {
123        self.append_word(utils::pad_usize(self.suffix_offset()));
124    }
125
126    /// Append a sequence length.
127    #[inline]
128    pub fn append_seq_len(&mut self, len: usize) {
129        self.append_word(utils::pad_usize(len));
130    }
131
132    /// Append a sequence of bytes as a packed sequence with a length prefix.
133    #[inline]
134    pub fn append_packed_seq(&mut self, bytes: &[u8]) {
135        self.append_seq_len(bytes.len());
136        self.append_bytes(bytes);
137    }
138
139    /// Shortcut for appending a token sequence.
140    #[inline]
141    pub fn append_head_tail<'a, T: TokenSeq<'a>>(&mut self, token: &T) {
142        token.encode_sequence(self);
143    }
144
145    /// Append a sequence of bytes, padding to the next word.
146    #[inline(always)]
147    fn append_bytes(&mut self, bytes: &[u8]) {
148        if bytes.is_empty() {
149            return;
150        }
151
152        let n_words = utils::words_for(bytes);
153        self.buf.reserve(n_words);
154        unsafe {
155            // set length before copying
156            // this is fine because we reserved above and we don't panic below
157            let len = self.buf.len();
158            self.buf.set_len(len + n_words);
159
160            // copy
161            let cnt = bytes.len();
162            let dst = self.buf.as_mut_ptr().add(len).cast::<u8>();
163            ptr::copy_nonoverlapping(bytes.as_ptr(), dst, cnt);
164
165            // set remaining bytes to zero if necessary
166            let rem = cnt % 32;
167            if rem != 0 {
168                let pad = 32 - rem;
169                ptr::write_bytes(dst.add(cnt), 0, pad);
170            }
171        }
172    }
173}
174
175/// ABI-encodes a single token.
176///
177/// You are probably looking for
178/// [`SolValue::abi_encode`](crate::SolValue::abi_encode) if
179/// you are not intending to use raw tokens.
180///
181/// See the [`abi`](super) module for more information.
182#[inline(always)]
183pub fn encode<'a, T: Token<'a>>(token: &T) -> Vec<u8> {
184    encode_sequence::<(T,)>(tuple_from_ref(token))
185}
186
187/// ABI-encodes a tuple as ABI function params, suitable for passing to a
188/// function.
189///
190/// You are probably looking for
191/// [`SolValue::abi_encode_params`](crate::SolValue::abi_encode_params) if
192/// you are not intending to use raw tokens.
193///
194/// See the [`abi`](super) module for more information.
195#[inline(always)]
196pub fn encode_params<'a, T: TokenSeq<'a>>(token: &T) -> Vec<u8> {
197    let encode = const { if T::IS_TUPLE { encode_sequence } else { encode } };
198    encode(token)
199}
200
201/// ABI-encodes a token sequence.
202///
203/// You are probably looking for
204/// [`SolValue::abi_encode_sequence`](crate::SolValue::abi_encode_sequence) if
205/// you are not intending to use raw tokens.
206///
207/// See the [`abi`](super) module for more information.
208#[inline]
209pub fn encode_sequence<'a, T: TokenSeq<'a>>(token: &T) -> Vec<u8> {
210    let mut enc = Encoder::with_capacity(token.total_words());
211    enc.append_head_tail(token);
212    enc.into_bytes()
213}
214
215/// Converts a reference to `T` into a reference to a tuple of length 1 (without
216/// copying).
217///
218/// Same as [`core::array::from_ref`].
219#[inline(always)]
220const fn tuple_from_ref<T>(s: &T) -> &(T,) {
221    // SAFETY: Converting `&T` to `&(T,)` is sound.
222    unsafe { &*(s as *const T).cast::<(T,)>() }
223}
224
225#[cfg(test)]
226mod tests {
227    use crate::{SolType, sol_data};
228    use alloc::{borrow::ToOwned, string::ToString, vec::Vec};
229    use alloy_primitives::{Address, U256, address, bytes, hex};
230    use alloy_sol_macro::sol;
231
232    #[test]
233    fn encode_address() {
234        let address = Address::from([0x11u8; 20]);
235        let expected = hex!("0000000000000000000000001111111111111111111111111111111111111111");
236        let encoded = sol_data::Address::abi_encode(&address);
237        assert_eq!(encoded, expected);
238        assert_eq!(encoded.len(), sol_data::Address::abi_encoded_size(&address));
239    }
240
241    #[test]
242    fn encode_dynamic_array_of_addresses() {
243        type MyTy = sol_data::Array<sol_data::Address>;
244        let data = vec![Address::from([0x11u8; 20]), Address::from([0x22u8; 20])];
245        let encoded = MyTy::abi_encode(&data);
246        let expected = hex!(
247            "
248			0000000000000000000000000000000000000000000000000000000000000020
249			0000000000000000000000000000000000000000000000000000000000000002
250			0000000000000000000000001111111111111111111111111111111111111111
251			0000000000000000000000002222222222222222222222222222222222222222
252		"
253        );
254        assert_eq!(encoded, expected);
255        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
256    }
257
258    #[test]
259    fn encode_fixed_array_of_addresses() {
260        type MyTy = sol_data::FixedArray<sol_data::Address, 2>;
261
262        let addresses = [Address::from([0x11u8; 20]), Address::from([0x22u8; 20])];
263
264        let encoded = MyTy::abi_encode(&addresses);
265        let encoded_params = MyTy::abi_encode_params(&addresses);
266        let expected = hex!(
267            "
268    		0000000000000000000000001111111111111111111111111111111111111111
269    		0000000000000000000000002222222222222222222222222222222222222222
270    	"
271        );
272        assert_eq!(encoded_params, expected);
273        assert_eq!(encoded, expected);
274        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&addresses));
275    }
276
277    #[test]
278    fn encode_two_addresses() {
279        type MyTy = (sol_data::Address, sol_data::Address);
280        let addresses = (Address::from([0x11u8; 20]), Address::from([0x22u8; 20]));
281
282        let encoded = MyTy::abi_encode_sequence(&addresses);
283        let encoded_params = MyTy::abi_encode_params(&addresses);
284        let expected = hex!(
285            "
286    		0000000000000000000000001111111111111111111111111111111111111111
287    		0000000000000000000000002222222222222222222222222222222222222222
288    	"
289        );
290        assert_eq!(encoded, expected);
291        assert_eq!(encoded_params, expected);
292        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&addresses));
293    }
294
295    #[test]
296    fn encode_fixed_array_of_dynamic_array_of_addresses() {
297        type MyTy = sol_data::FixedArray<sol_data::Array<sol_data::Address>, 2>;
298        let data = [
299            vec![Address::from([0x11u8; 20]), Address::from([0x22u8; 20])],
300            vec![Address::from([0x33u8; 20]), Address::from([0x44u8; 20])],
301        ];
302
303        let expected = hex!(
304            "
305    		0000000000000000000000000000000000000000000000000000000000000020
306    		0000000000000000000000000000000000000000000000000000000000000040
307    		00000000000000000000000000000000000000000000000000000000000000a0
308    		0000000000000000000000000000000000000000000000000000000000000002
309    		0000000000000000000000001111111111111111111111111111111111111111
310    		0000000000000000000000002222222222222222222222222222222222222222
311    		0000000000000000000000000000000000000000000000000000000000000002
312    		0000000000000000000000003333333333333333333333333333333333333333
313    		0000000000000000000000004444444444444444444444444444444444444444
314    	"
315        );
316        let encoded = MyTy::abi_encode(&data);
317        assert_eq!(encoded, expected);
318        let encoded_params = MyTy::abi_encode_params(&data);
319        assert_eq!(encoded_params, expected);
320
321        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
322    }
323
324    #[test]
325    fn encode_dynamic_array_of_fixed_array_of_addresses() {
326        type TwoAddrs = sol_data::FixedArray<sol_data::Address, 2>;
327        type MyTy = sol_data::Array<TwoAddrs>;
328
329        let data = vec![
330            [Address::from([0x11u8; 20]), Address::from([0x22u8; 20])],
331            [Address::from([0x33u8; 20]), Address::from([0x44u8; 20])],
332        ];
333
334        let expected = hex!(
335            "
336    		0000000000000000000000000000000000000000000000000000000000000020
337    		0000000000000000000000000000000000000000000000000000000000000002
338    		0000000000000000000000001111111111111111111111111111111111111111
339    		0000000000000000000000002222222222222222222222222222222222222222
340    		0000000000000000000000003333333333333333333333333333333333333333
341    		0000000000000000000000004444444444444444444444444444444444444444
342    	"
343        );
344        // a DynSeq at top level ALWAYS has extra indirection
345        let encoded = MyTy::abi_encode(&data);
346        assert_eq!(encoded, expected);
347        let encoded_params = MyTy::abi_encode_params(&data);
348        assert_eq!(encoded_params, expected);
349        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
350    }
351
352    #[test]
353    fn encode_dynamic_array_of_dynamic_arrays() {
354        type MyTy = sol_data::Array<sol_data::Array<sol_data::Address>>;
355
356        let data = vec![vec![Address::from([0x11u8; 20])], vec![Address::from([0x22u8; 20])]];
357
358        let expected = hex!(
359            "
360    		0000000000000000000000000000000000000000000000000000000000000020
361    		0000000000000000000000000000000000000000000000000000000000000002
362    		0000000000000000000000000000000000000000000000000000000000000040
363    		0000000000000000000000000000000000000000000000000000000000000080
364    		0000000000000000000000000000000000000000000000000000000000000001
365    		0000000000000000000000001111111111111111111111111111111111111111
366    		0000000000000000000000000000000000000000000000000000000000000001
367    		0000000000000000000000002222222222222222222222222222222222222222
368    	"
369        );
370        // a DynSeq at top level ALWAYS has extra indirection
371        let encoded = MyTy::abi_encode(&data);
372        assert_eq!(encoded, expected);
373        let encoded_params = MyTy::abi_encode_params(&data);
374        assert_eq!(encoded_params, expected);
375        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
376    }
377
378    #[test]
379    fn encode_dynamic_array_of_dynamic_arrays2() {
380        type MyTy = sol_data::Array<sol_data::Array<sol_data::Address>>;
381
382        let data = vec![
383            vec![Address::from([0x11u8; 20]), Address::from([0x22u8; 20])],
384            vec![Address::from([0x33u8; 20]), Address::from([0x44u8; 20])],
385        ];
386        let expected = hex!(
387            "
388    		0000000000000000000000000000000000000000000000000000000000000020
389    		0000000000000000000000000000000000000000000000000000000000000002
390    		0000000000000000000000000000000000000000000000000000000000000040
391    		00000000000000000000000000000000000000000000000000000000000000a0
392    		0000000000000000000000000000000000000000000000000000000000000002
393    		0000000000000000000000001111111111111111111111111111111111111111
394    		0000000000000000000000002222222222222222222222222222222222222222
395    		0000000000000000000000000000000000000000000000000000000000000002
396    		0000000000000000000000003333333333333333333333333333333333333333
397    		0000000000000000000000004444444444444444444444444444444444444444
398    	"
399        );
400        // a DynSeq at top level ALWAYS has extra indirection
401        let encoded = MyTy::abi_encode(&data);
402        assert_eq!(encoded, expected);
403        let encoded_params = MyTy::abi_encode_params(&data);
404        assert_eq!(encoded_params, expected);
405        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
406    }
407
408    #[test]
409    fn encode_fixed_array_of_fixed_arrays() {
410        type MyTy = sol_data::FixedArray<sol_data::FixedArray<sol_data::Address, 2>, 2>;
411
412        let fixed = [
413            [Address::from([0x11u8; 20]), Address::from([0x22u8; 20])],
414            [Address::from([0x33u8; 20]), Address::from([0x44u8; 20])],
415        ];
416
417        let encoded = MyTy::abi_encode_sequence(&fixed);
418        let encoded_params = MyTy::abi_encode_params(&fixed);
419        let expected = hex!(
420            "
421    		0000000000000000000000001111111111111111111111111111111111111111
422    		0000000000000000000000002222222222222222222222222222222222222222
423    		0000000000000000000000003333333333333333333333333333333333333333
424    		0000000000000000000000004444444444444444444444444444444444444444
425    	"
426        );
427        // a non-dynamic FixedSeq at top level NEVER has extra indirection
428        assert_eq!(encoded, expected);
429        assert_eq!(encoded_params, expected);
430        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&fixed));
431    }
432
433    #[test]
434    fn encode_fixed_array_of_static_tuples_followed_by_dynamic_type() {
435        type Tup = (sol_data::Uint<256>, sol_data::Uint<256>, sol_data::Address);
436        type Fixed = sol_data::FixedArray<Tup, 2>;
437        type MyTy = (Fixed, sol_data::String);
438
439        let data = (
440            [
441                (U256::from(93523141), U256::from(352332135), Address::from([0x44u8; 20])),
442                (U256::from(12411), U256::from(451), Address::from([0x22u8; 20])),
443            ],
444            "gavofyork".to_string(),
445        );
446
447        let expected = hex!(
448            "
449    		0000000000000000000000000000000000000000000000000000000005930cc5
450    		0000000000000000000000000000000000000000000000000000000015002967
451    		0000000000000000000000004444444444444444444444444444444444444444
452    		000000000000000000000000000000000000000000000000000000000000307b
453    		00000000000000000000000000000000000000000000000000000000000001c3
454    		0000000000000000000000002222222222222222222222222222222222222222
455    		00000000000000000000000000000000000000000000000000000000000000e0
456    		0000000000000000000000000000000000000000000000000000000000000009
457    		6761766f66796f726b0000000000000000000000000000000000000000000000
458    	"
459        );
460
461        let encoded = MyTy::abi_encode(&data);
462        let encoded_params = MyTy::abi_encode_params(&data);
463        assert_ne!(encoded, expected);
464        assert_eq!(encoded_params, expected);
465        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
466    }
467
468    #[test]
469    fn encode_empty_array() {
470        type MyTy0 = sol_data::Array<sol_data::Address>;
471
472        let data: Vec<Address> = vec![];
473
474        // Empty arrays
475        let encoded = MyTy0::abi_encode_params(&data);
476        let expected = hex!(
477            "
478    		0000000000000000000000000000000000000000000000000000000000000020
479    		0000000000000000000000000000000000000000000000000000000000000000
480    	    "
481        );
482
483        assert_eq!(encoded, expected);
484        assert_eq!(encoded.len(), MyTy0::abi_encoded_size(&data));
485
486        type MyTy = (sol_data::Array<sol_data::Address>, sol_data::Array<sol_data::Address>);
487        let data: (Vec<Address>, Vec<Address>) = (vec![], vec![]);
488
489        let expected = hex!(
490            "
491    		0000000000000000000000000000000000000000000000000000000000000040
492    		0000000000000000000000000000000000000000000000000000000000000060
493    		0000000000000000000000000000000000000000000000000000000000000000
494    		0000000000000000000000000000000000000000000000000000000000000000
495    	    "
496        );
497
498        // Empty arrays
499        let encoded = MyTy::abi_encode(&data);
500        assert_ne!(encoded, expected);
501
502        let encoded_params = MyTy::abi_encode_params(&data);
503        assert_eq!(encoded_params, expected);
504        assert_eq!(encoded_params.len() + 32, encoded.len());
505        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
506
507        type MyTy2 = (
508            sol_data::Array<sol_data::Array<sol_data::Address>>,
509            sol_data::Array<sol_data::Array<sol_data::Address>>,
510        );
511
512        let data: (Vec<Vec<Address>>, Vec<Vec<Address>>) = (vec![vec![]], vec![vec![]]);
513
514        // Nested empty arrays
515        let expected = hex!(
516            "
517    		0000000000000000000000000000000000000000000000000000000000000040
518    		00000000000000000000000000000000000000000000000000000000000000a0
519    		0000000000000000000000000000000000000000000000000000000000000001
520    		0000000000000000000000000000000000000000000000000000000000000020
521    		0000000000000000000000000000000000000000000000000000000000000000
522    		0000000000000000000000000000000000000000000000000000000000000001
523    		0000000000000000000000000000000000000000000000000000000000000020
524    		0000000000000000000000000000000000000000000000000000000000000000
525    	"
526        );
527        // A Dynamic FixedSeq may be a top-level sequence to `encode` or may
528        // itself be an item in a top-level sequence. Which is to say, it could
529        // be (as `abi_encode(T)` or `abi_encode((T,))`). This test was `abi_encode(T)`
530        let encoded = MyTy2::abi_encode(&data);
531        assert_ne!(encoded, expected);
532        let encoded_params = MyTy2::abi_encode_params(&data);
533
534        assert_eq!(encoded_params, expected);
535        assert_eq!(encoded_params.len() + 32, encoded.len());
536        assert_eq!(encoded.len(), MyTy2::abi_encoded_size(&data));
537    }
538
539    #[test]
540    fn encode_empty_bytes() {
541        let bytes = Vec::<u8>::new();
542
543        let encoded = sol_data::Bytes::abi_encode(&bytes);
544        let expected = hex!(
545            "
546    		0000000000000000000000000000000000000000000000000000000000000020
547    		0000000000000000000000000000000000000000000000000000000000000000
548    	"
549        );
550        assert_eq!(encoded, expected);
551        assert_eq!(encoded.len(), sol_data::Bytes::abi_encoded_size(&bytes));
552    }
553
554    #[test]
555    fn encode_bytes() {
556        let bytes = vec![0x12, 0x34];
557
558        let encoded = sol_data::Bytes::abi_encode(&bytes);
559        let expected = hex!(
560            "
561    		0000000000000000000000000000000000000000000000000000000000000020
562    		0000000000000000000000000000000000000000000000000000000000000002
563    		1234000000000000000000000000000000000000000000000000000000000000
564    	"
565        );
566        assert_eq!(encoded, expected);
567        assert_eq!(encoded.len(), sol_data::Bytes::abi_encoded_size(&bytes));
568    }
569
570    #[test]
571    fn encode_fixed_bytes() {
572        let encoded = sol_data::FixedBytes::<2>::abi_encode(&[0x12, 0x34]);
573        let expected = hex!("1234000000000000000000000000000000000000000000000000000000000000");
574        assert_eq!(encoded, expected);
575        assert_eq!(encoded.len(), sol_data::FixedBytes::<2>::abi_encoded_size(&[0x12, 0x34]));
576    }
577
578    #[test]
579    fn encode_empty_string() {
580        let s = "";
581        let encoded = sol_data::String::abi_encode(s);
582        let expected = hex!(
583            "
584    		0000000000000000000000000000000000000000000000000000000000000020
585    		0000000000000000000000000000000000000000000000000000000000000000
586    	"
587        );
588        assert_eq!(encoded, expected);
589        assert_eq!(encoded.len(), sol_data::String::abi_encoded_size(&s));
590    }
591
592    #[test]
593    fn encode_string() {
594        let s = "gavofyork".to_string();
595        let encoded = sol_data::String::abi_encode(&s);
596        let expected = hex!(
597            "
598    		0000000000000000000000000000000000000000000000000000000000000020
599    		0000000000000000000000000000000000000000000000000000000000000009
600    		6761766f66796f726b0000000000000000000000000000000000000000000000
601    	"
602        );
603        assert_eq!(encoded, expected);
604        assert_eq!(encoded.len(), sol_data::String::abi_encoded_size(&s));
605    }
606
607    #[test]
608    fn encode_bytes2() {
609        let bytes = hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec();
610        let encoded = sol_data::Bytes::abi_encode(&bytes);
611        let expected = hex!(
612            "
613    		0000000000000000000000000000000000000000000000000000000000000020
614    		000000000000000000000000000000000000000000000000000000000000001f
615    		1000000000000000000000000000000000000000000000000000000000000200
616    	"
617        );
618        assert_eq!(encoded, expected);
619        assert_eq!(encoded.len(), sol_data::Bytes::abi_encoded_size(&bytes));
620    }
621
622    #[test]
623    fn encode_bytes3() {
624        let bytes = hex!(
625            "
626    		1000000000000000000000000000000000000000000000000000000000000000
627    		1000000000000000000000000000000000000000000000000000000000000000
628    	"
629        );
630        let encoded = sol_data::Bytes::abi_encode(&bytes);
631        let expected = hex!(
632            "
633    		0000000000000000000000000000000000000000000000000000000000000020
634    		0000000000000000000000000000000000000000000000000000000000000040
635    		1000000000000000000000000000000000000000000000000000000000000000
636    		1000000000000000000000000000000000000000000000000000000000000000
637    	"
638        );
639        assert_eq!(encoded, expected);
640        assert_eq!(encoded.len(), sol_data::Bytes::abi_encoded_size(&bytes));
641    }
642
643    #[test]
644    fn encode_two_bytes() {
645        type MyTy = (sol_data::Bytes, sol_data::Bytes);
646
647        let bytes = (
648            hex!("10000000000000000000000000000000000000000000000000000000000002").to_vec(),
649            hex!("0010000000000000000000000000000000000000000000000000000000000002").to_vec(),
650        );
651        let encoded = MyTy::abi_encode(&bytes);
652        let encoded_params = MyTy::abi_encode_params(&bytes);
653        let expected = hex!(
654            "
655    		0000000000000000000000000000000000000000000000000000000000000040
656    		0000000000000000000000000000000000000000000000000000000000000080
657    		000000000000000000000000000000000000000000000000000000000000001f
658    		1000000000000000000000000000000000000000000000000000000000000200
659    		0000000000000000000000000000000000000000000000000000000000000020
660    		0010000000000000000000000000000000000000000000000000000000000002
661    	"
662        );
663        // A Dynamic FixedSeq may be a top-level sequence to `encode` or may
664        // itself be an item in a top-level sequence. Which is to say, it could
665        // be (as `abi_encode(T)` or `abi_encode((T,))`). This test was `abi_encode(T)`
666        assert_ne!(encoded, expected);
667        assert_eq!(encoded_params, expected);
668        assert_eq!(encoded_params.len() + 32, encoded.len());
669        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&bytes));
670    }
671
672    #[test]
673    fn encode_uint() {
674        let uint = 4;
675        let encoded = sol_data::Uint::<8>::abi_encode(&uint);
676        let expected = hex!("0000000000000000000000000000000000000000000000000000000000000004");
677        assert_eq!(encoded, expected);
678        assert_eq!(encoded.len(), sol_data::Uint::<8>::abi_encoded_size(&uint));
679    }
680
681    #[test]
682    fn encode_int() {
683        let int = 4;
684        let encoded = sol_data::Int::<8>::abi_encode(&int);
685        let expected = hex!("0000000000000000000000000000000000000000000000000000000000000004");
686        assert_eq!(encoded, expected);
687        assert_eq!(encoded.len(), sol_data::Int::<8>::abi_encoded_size(&int));
688    }
689
690    #[test]
691    fn encode_bool() {
692        let encoded = sol_data::Bool::abi_encode(&true);
693        let expected = hex!("0000000000000000000000000000000000000000000000000000000000000001");
694        assert_eq!(encoded, expected);
695        assert_eq!(encoded.len(), sol_data::Bool::abi_encoded_size(&true));
696    }
697
698    #[test]
699    fn encode_bool2() {
700        let encoded = sol_data::Bool::abi_encode(&false);
701        let expected = hex!("0000000000000000000000000000000000000000000000000000000000000000");
702        assert_eq!(encoded, expected);
703        assert_eq!(encoded.len(), sol_data::Bool::abi_encoded_size(&false));
704    }
705
706    #[test]
707    fn comprehensive_test() {
708        type MyTy = (sol_data::Uint<8>, sol_data::Bytes, sol_data::Uint<8>, sol_data::Bytes);
709
710        let bytes = hex!(
711            "
712    		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
713    		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
714    	"
715        );
716
717        let data = (5, bytes, 3, bytes);
718
719        let encoded = MyTy::abi_encode(&data);
720        let encoded_params = MyTy::abi_encode_params(&data);
721
722        let expected = hex!(
723            "
724    		0000000000000000000000000000000000000000000000000000000000000005
725    		0000000000000000000000000000000000000000000000000000000000000080
726    		0000000000000000000000000000000000000000000000000000000000000003
727    		00000000000000000000000000000000000000000000000000000000000000e0
728    		0000000000000000000000000000000000000000000000000000000000000040
729    		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
730    		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
731    		0000000000000000000000000000000000000000000000000000000000000040
732    		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
733    		131a3afc00d1b1e3461b955e53fc866dcf303b3eb9f4c16f89e388930f48134b
734    	"
735        );
736        // A Dynamic FixedSeq may be a top-level sequence to `encode` or may
737        // itself be an item in a top-level sequence. Which is to say, it could
738        // be (as `abi_encode(T)` or `abi_encode((T,))`). This test was `abi_encode(T)`
739        assert_ne!(encoded, expected);
740        assert_eq!(encoded_params, expected);
741        assert_eq!(encoded_params.len() + 32, encoded.len());
742        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
743    }
744
745    #[test]
746    fn comprehensive_test2() {
747        type MyTy = (
748            sol_data::Bool,
749            sol_data::String,
750            sol_data::Uint<8>,
751            sol_data::Uint<8>,
752            sol_data::Uint<8>,
753            sol_data::Array<sol_data::Uint<8>>,
754        );
755
756        let data = (true, "gavofyork".to_string(), 2, 3, 4, vec![5, 6, 7]);
757
758        let expected = hex!(
759            "
760    		0000000000000000000000000000000000000000000000000000000000000001
761    		00000000000000000000000000000000000000000000000000000000000000c0
762    		0000000000000000000000000000000000000000000000000000000000000002
763    		0000000000000000000000000000000000000000000000000000000000000003
764    		0000000000000000000000000000000000000000000000000000000000000004
765    		0000000000000000000000000000000000000000000000000000000000000100
766    		0000000000000000000000000000000000000000000000000000000000000009
767    		6761766f66796f726b0000000000000000000000000000000000000000000000
768    		0000000000000000000000000000000000000000000000000000000000000003
769    		0000000000000000000000000000000000000000000000000000000000000005
770    		0000000000000000000000000000000000000000000000000000000000000006
771    		0000000000000000000000000000000000000000000000000000000000000007
772    	"
773        );
774        // A Dynamic FixedSeq may be a top-level sequence to `encode` or may
775        // itself be an item in a top-level sequence. Which is to say, it could
776        // be (as `abi_encode(T)` or `abi_encode((T,))`). This test was `abi_encode(T)`
777        let encoded = MyTy::abi_encode(&data);
778        assert_ne!(encoded, expected);
779        let encoded_params = MyTy::abi_encode_params(&data);
780        assert_eq!(encoded_params, expected);
781        assert_eq!(encoded_params.len() + 32, encoded.len());
782        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
783    }
784
785    #[test]
786    fn encode_dynamic_array_of_bytes() {
787        type MyTy = sol_data::Array<sol_data::Bytes>;
788        let data = vec![
789            hex!("019c80031b20d5e69c8093a571162299032018d913930d93ab320ae5ea44a4218a274f00d607")
790                .to_vec(),
791        ];
792
793        let expected = hex!(
794            "
795    		0000000000000000000000000000000000000000000000000000000000000020
796    		0000000000000000000000000000000000000000000000000000000000000001
797    		0000000000000000000000000000000000000000000000000000000000000020
798    		0000000000000000000000000000000000000000000000000000000000000026
799    		019c80031b20d5e69c8093a571162299032018d913930d93ab320ae5ea44a421
800    		8a274f00d6070000000000000000000000000000000000000000000000000000
801    	"
802        );
803        // a DynSeq at top level ALWAYS has extra indirection
804        let encoded = MyTy::abi_encode(&data);
805        assert_eq!(encoded, expected);
806        let encoded_params = MyTy::abi_encode_params(&data);
807        assert_eq!(encoded_params, expected);
808        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
809    }
810
811    #[test]
812    fn encode_dynamic_array_of_bytes2() {
813        type MyTy = sol_data::Array<sol_data::Bytes>;
814
815        let data = vec![
816            hex!("4444444444444444444444444444444444444444444444444444444444444444444444444444")
817                .to_vec(),
818            hex!("6666666666666666666666666666666666666666666666666666666666666666666666666666")
819                .to_vec(),
820        ];
821
822        let expected = hex!(
823            "
824    		0000000000000000000000000000000000000000000000000000000000000020
825    		0000000000000000000000000000000000000000000000000000000000000002
826    		0000000000000000000000000000000000000000000000000000000000000040
827    		00000000000000000000000000000000000000000000000000000000000000a0
828    		0000000000000000000000000000000000000000000000000000000000000026
829    		4444444444444444444444444444444444444444444444444444444444444444
830    		4444444444440000000000000000000000000000000000000000000000000000
831    		0000000000000000000000000000000000000000000000000000000000000026
832    		6666666666666666666666666666666666666666666666666666666666666666
833    		6666666666660000000000000000000000000000000000000000000000000000
834    	"
835        );
836        // a DynSeq at top level ALWAYS has extra indirection
837        let encoded = MyTy::abi_encode(&data);
838        assert_eq!(encoded, expected);
839        let encoded_params = MyTy::abi_encode_params(&data);
840        assert_eq!(encoded_params, expected);
841        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
842    }
843
844    #[test]
845    fn encode_static_tuple_of_addresses() {
846        type MyTy = (sol_data::Address, sol_data::Address);
847        let data = (Address::from([0x11u8; 20]), Address::from([0x22u8; 20]));
848
849        let encoded = MyTy::abi_encode_sequence(&data);
850        let encoded_params = MyTy::abi_encode_params(&data);
851
852        let expected = hex!(
853            "
854    		0000000000000000000000001111111111111111111111111111111111111111
855    		0000000000000000000000002222222222222222222222222222222222222222
856    	"
857        );
858        assert_eq!(encoded, expected);
859        assert_eq!(encoded_params, expected);
860        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
861    }
862
863    #[test]
864    fn encode_dynamic_tuple() {
865        type MyTy = (sol_data::String, sol_data::String);
866        let data = ("gavofyork".to_string(), "gavofyork".to_string());
867
868        let expected = hex!(
869            "
870    		0000000000000000000000000000000000000000000000000000000000000020
871    		0000000000000000000000000000000000000000000000000000000000000040
872    		0000000000000000000000000000000000000000000000000000000000000080
873    		0000000000000000000000000000000000000000000000000000000000000009
874    		6761766f66796f726b0000000000000000000000000000000000000000000000
875    		0000000000000000000000000000000000000000000000000000000000000009
876    		6761766f66796f726b0000000000000000000000000000000000000000000000
877    	"
878        );
879        // a dynamic FixedSeq at top level should start with indirection
880        // when not param encoded.
881        let encoded = MyTy::abi_encode(&data);
882        assert_eq!(encoded, expected);
883        let encoded_params = MyTy::abi_encode_params(&data);
884        assert_ne!(encoded_params, expected);
885        assert_eq!(encoded_params.len() + 32, encoded.len());
886        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
887    }
888
889    #[test]
890    fn encode_dynamic_tuple_of_bytes2() {
891        type MyTy = (sol_data::Bytes, sol_data::Bytes);
892
893        let data = (
894            hex!("4444444444444444444444444444444444444444444444444444444444444444444444444444")
895                .to_vec(),
896            hex!("6666666666666666666666666666666666666666666666666666666666666666666666666666")
897                .to_vec(),
898        );
899
900        let encoded = MyTy::abi_encode(&data);
901        let encoded_params = MyTy::abi_encode_params(&data);
902
903        let expected = hex!(
904            "
905    		0000000000000000000000000000000000000000000000000000000000000020
906    		0000000000000000000000000000000000000000000000000000000000000040
907    		00000000000000000000000000000000000000000000000000000000000000a0
908    		0000000000000000000000000000000000000000000000000000000000000026
909    		4444444444444444444444444444444444444444444444444444444444444444
910    		4444444444440000000000000000000000000000000000000000000000000000
911    		0000000000000000000000000000000000000000000000000000000000000026
912    		6666666666666666666666666666666666666666666666666666666666666666
913    		6666666666660000000000000000000000000000000000000000000000000000
914    	"
915        );
916        // a dynamic FixedSeq at top level should start with indirection
917        // when not param encoded.
918        assert_eq!(encoded, expected);
919        assert_ne!(encoded_params, expected);
920        assert_eq!(encoded_params.len() + 32, encoded.len());
921        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
922    }
923
924    #[test]
925    fn encode_complex_tuple() {
926        type MyTy = (sol_data::Uint<256>, sol_data::String, sol_data::Address, sol_data::Address);
927
928        let data = (
929            U256::from_be_bytes::<32>([0x11u8; 32]),
930            "gavofyork".to_owned(),
931            Address::from([0x11u8; 20]),
932            Address::from([0x22u8; 20]),
933        );
934
935        let expected = hex!(
936            "
937            0000000000000000000000000000000000000000000000000000000000000020
938            1111111111111111111111111111111111111111111111111111111111111111
939            0000000000000000000000000000000000000000000000000000000000000080
940            0000000000000000000000001111111111111111111111111111111111111111
941    		0000000000000000000000002222222222222222222222222222222222222222
942    		0000000000000000000000000000000000000000000000000000000000000009
943    		6761766f66796f726b0000000000000000000000000000000000000000000000
944    	"
945        );
946        // a dynamic FixedSeq at top level should start with indirection
947        // when not param encoded.
948        let encoded = MyTy::abi_encode(&data);
949        assert_eq!(encoded, expected);
950        let encoded_params = MyTy::abi_encode_params(&data);
951        assert_ne!(encoded_params, expected);
952        assert_eq!(encoded_params.len() + 32, encoded.len());
953        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
954    }
955
956    #[test]
957    fn encode_nested_tuple() {
958        type MyTy = (
959            sol_data::String,
960            sol_data::Bool,
961            sol_data::String,
962            (sol_data::String, sol_data::String, (sol_data::String, sol_data::String)),
963        );
964
965        let data = (
966            "test".to_string(),
967            true,
968            "cyborg".to_string(),
969            ("night".to_string(), "day".to_string(), ("weee".to_string(), "funtests".to_string())),
970        );
971
972        let encoded = MyTy::abi_encode(&data);
973        let encoded_params = MyTy::abi_encode_sequence(&data);
974
975        let expected = hex!(
976            "
977    		0000000000000000000000000000000000000000000000000000000000000020
978    		0000000000000000000000000000000000000000000000000000000000000080
979    		0000000000000000000000000000000000000000000000000000000000000001
980    		00000000000000000000000000000000000000000000000000000000000000c0
981    		0000000000000000000000000000000000000000000000000000000000000100
982    		0000000000000000000000000000000000000000000000000000000000000004
983    		7465737400000000000000000000000000000000000000000000000000000000
984    		0000000000000000000000000000000000000000000000000000000000000006
985    		6379626f72670000000000000000000000000000000000000000000000000000
986    		0000000000000000000000000000000000000000000000000000000000000060
987    		00000000000000000000000000000000000000000000000000000000000000a0
988    		00000000000000000000000000000000000000000000000000000000000000e0
989    		0000000000000000000000000000000000000000000000000000000000000005
990    		6e69676874000000000000000000000000000000000000000000000000000000
991    		0000000000000000000000000000000000000000000000000000000000000003
992    		6461790000000000000000000000000000000000000000000000000000000000
993    		0000000000000000000000000000000000000000000000000000000000000040
994    		0000000000000000000000000000000000000000000000000000000000000080
995    		0000000000000000000000000000000000000000000000000000000000000004
996    		7765656500000000000000000000000000000000000000000000000000000000
997    		0000000000000000000000000000000000000000000000000000000000000008
998    		66756e7465737473000000000000000000000000000000000000000000000000
999    	"
1000        );
1001        // a dynamic FixedSeq at top level should start with indirection
1002        // when not param encoded
1003        assert_eq!(encoded, expected);
1004        assert_ne!(encoded_params, expected);
1005        assert_eq!(encoded_params.len() + 32, encoded.len());
1006        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
1007    }
1008
1009    #[test]
1010    fn encode_params_containing_dynamic_tuple() {
1011        type MyTy = (
1012            sol_data::Address,
1013            (sol_data::Bool, sol_data::String, sol_data::String),
1014            sol_data::Address,
1015            sol_data::Address,
1016            sol_data::Bool,
1017        );
1018        let data = (
1019            Address::from([0x22u8; 20]),
1020            (true, "spaceship".to_owned(), "cyborg".to_owned()),
1021            Address::from([0x33u8; 20]),
1022            Address::from([0x44u8; 20]),
1023            false,
1024        );
1025
1026        let encoded_single = MyTy::abi_encode(&data);
1027        let encoded = MyTy::abi_encode_sequence(&data);
1028
1029        let expected = hex!(
1030            "
1031    		0000000000000000000000002222222222222222222222222222222222222222
1032    		00000000000000000000000000000000000000000000000000000000000000a0
1033    		0000000000000000000000003333333333333333333333333333333333333333
1034    		0000000000000000000000004444444444444444444444444444444444444444
1035    		0000000000000000000000000000000000000000000000000000000000000000
1036    		0000000000000000000000000000000000000000000000000000000000000001
1037    		0000000000000000000000000000000000000000000000000000000000000060
1038    		00000000000000000000000000000000000000000000000000000000000000a0
1039    		0000000000000000000000000000000000000000000000000000000000000009
1040    		7370616365736869700000000000000000000000000000000000000000000000
1041    		0000000000000000000000000000000000000000000000000000000000000006
1042    		6379626f72670000000000000000000000000000000000000000000000000000
1043    	"
1044        );
1045        // A Dynamic FixedSeq may be a top-level sequence to `encode` or may
1046        // itself be an item in a top-level sequence. Which is to say, it could
1047        // be (as `abi_encode(T)` or `abi_encode((T,))`). This test was `abi_encode(T)`
1048        assert_ne!(encoded_single, expected);
1049        assert_eq!(encoded, expected);
1050        assert_eq!(encoded.len() + 32, encoded_single.len());
1051        assert_eq!(encoded_single.len(), MyTy::abi_encoded_size(&data));
1052    }
1053
1054    #[test]
1055    fn encode_params_containing_static_tuple() {
1056        type MyTy = (
1057            sol_data::Address,
1058            (sol_data::Address, sol_data::Bool, sol_data::Bool),
1059            sol_data::Address,
1060            sol_data::Address,
1061        );
1062
1063        let data = (
1064            Address::from([0x11u8; 20]),
1065            (Address::from([0x22u8; 20]), true, false),
1066            Address::from([0x33u8; 20]),
1067            Address::from([0x44u8; 20]),
1068        );
1069
1070        let encoded = MyTy::abi_encode_sequence(&data);
1071        let encoded_params = MyTy::abi_encode_params(&data);
1072
1073        let expected = hex!(
1074            "
1075    		0000000000000000000000001111111111111111111111111111111111111111
1076    		0000000000000000000000002222222222222222222222222222222222222222
1077    		0000000000000000000000000000000000000000000000000000000000000001
1078    		0000000000000000000000000000000000000000000000000000000000000000
1079    		0000000000000000000000003333333333333333333333333333333333333333
1080    		0000000000000000000000004444444444444444444444444444444444444444
1081    	"
1082        );
1083
1084        // a static FixedSeq should NEVER indirect
1085        assert_eq!(encoded, expected);
1086        assert_eq!(encoded_params, expected);
1087        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
1088    }
1089
1090    #[test]
1091    fn encode_dynamic_tuple_with_nested_static_tuples() {
1092        type MyTy = (((sol_data::Bool, sol_data::Uint<16>),), sol_data::Array<sol_data::Uint<16>>);
1093
1094        let data = (((false, 0x777),), vec![0x42, 0x1337]);
1095
1096        let encoded = MyTy::abi_encode(&data);
1097        let encoded_params = MyTy::abi_encode_params(&data);
1098
1099        let expected = hex!(
1100            "
1101    		0000000000000000000000000000000000000000000000000000000000000020
1102    		0000000000000000000000000000000000000000000000000000000000000000
1103    		0000000000000000000000000000000000000000000000000000000000000777
1104    		0000000000000000000000000000000000000000000000000000000000000060
1105    		0000000000000000000000000000000000000000000000000000000000000002
1106    		0000000000000000000000000000000000000000000000000000000000000042
1107    		0000000000000000000000000000000000000000000000000000000000001337
1108    	"
1109        );
1110        // a dynamic FixedSeq at top level should start with indirection
1111        // when not param encoded
1112        assert_eq!(encoded, expected);
1113        assert_ne!(encoded_params, expected);
1114        assert_eq!(encoded_params.len() + 32, encoded.len());
1115        assert_eq!(encoded.len(), MyTy::abi_encoded_size(&data));
1116    }
1117
1118    // https://github.com/foundry-rs/foundry/issues/7280
1119    #[test]
1120    fn encode_empty_bytes_array_in_tuple() {
1121        type MyTy = sol! { (bytes, address, bytes[]) };
1122
1123        let data = (
1124            Vec::from(bytes!("09736b79736b79736b79026f7300")),
1125            address!("0xB7b54cd129e6D8B24e6AE652a473449B273eE3E4"),
1126            Vec::<Vec<u8>>::new(),
1127        );
1128
1129        let encoded_params = MyTy::abi_encode_params(&data);
1130
1131        let expected = hex!(
1132            "
1133            0000000000000000000000000000000000000000000000000000000000000060
1134            000000000000000000000000B7b54cd129e6D8B24e6AE652a473449B273eE3E4
1135            00000000000000000000000000000000000000000000000000000000000000a0
1136            000000000000000000000000000000000000000000000000000000000000000e
1137            09736b79736b79736b79026f7300000000000000000000000000000000000000
1138            0000000000000000000000000000000000000000000000000000000000000000
1139    	"
1140        );
1141        assert_eq!(encoded_params, expected);
1142    }
1143}