Skip to main content

fluentbase_codec/
evm.rs

1use crate::{
2    alloc::string::ToString,
3    bytes_codec::{read_bytes, read_bytes_header, write_bytes},
4    encoder::{align_up, get_aligned_slice, is_big_endian, write_u32_aligned, Encoder},
5    error::{CodecError, DecodingError},
6};
7use alloc::string::String;
8use alloy_primitives::{Address, Bytes, FixedBytes, Signed, Uint};
9use byteorder::ByteOrder;
10use bytes::{Buf, BytesMut};
11
12impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, true, false> for Bytes {
13    const HEADER_SIZE: usize = 32;
14    const IS_DYNAMIC: bool = true;
15
16    /// Encode the bytes into the buffer for Solidity mode.
17    /// First, we encode the header and write it to the given offset.
18    /// After that, we encode the actual data and write it to the end of the buffer.
19    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
20        let aligned_header_size =
21            align_up::<32>(<Self as Encoder<B, ALIGN, true, false>>::HEADER_SIZE);
22
23        // Ensure the buffer has enough space for the offset + header size
24        if buf.len() < offset + aligned_header_size {
25            buf.resize(offset + aligned_header_size, 0);
26        }
27
28        // Write the offset of the data (current length of the buffer)
29        write_u32_aligned::<B, ALIGN>(buf, offset, buf.len() as u32);
30
31        // Write the actual data to the buffer at the current length
32        let _ = write_bytes::<B, ALIGN, true>(buf, buf.len(), self, self.len() as u32);
33
34        // Add padding if necessary to ensure the buffer remains aligned
35        if !buf.len().is_multiple_of(ALIGN) {
36            let padding = ALIGN - (buf.len() % ALIGN);
37            buf.resize(buf.len() + padding, 0);
38        }
39
40        Ok(())
41    }
42
43    /// Decode the bytes from the buffer for Solidity mode.
44    /// Reads the header to get the data offset and size, then reads the actual data.
45    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
46        Ok(Self::from(read_bytes::<B, ALIGN, true>(buf, offset)?))
47    }
48
49    /// Partially decode the bytes from the buffer for Solidity mode.
50    /// Returns the data offset and size without reading the actual data.
51    fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
52        read_bytes_header::<B, ALIGN, true>(buf, offset)
53    }
54}
55
56impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, false, false> for Bytes {
57    const HEADER_SIZE: usize = size_of::<u32>() * 2;
58    const IS_DYNAMIC: bool = true;
59
60    /// Encode the bytes into the buffer.
61    /// First, we encode the header and write it to the given offset.
62    /// After that, we encode the actual data and write it to the end of the buffer.
63    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
64        let aligned_el_size = align_up::<ALIGN>(4);
65
66        // Ensure the buffer has enough space for the offset and header size
67        if buf.len() < offset + aligned_el_size {
68            buf.resize(offset + aligned_el_size, 0);
69        }
70
71        let _ = write_bytes::<B, ALIGN, false>(buf, offset, self, self.len() as u32);
72
73        // Add padding if necessary to ensure the buffer remains aligned
74        if !buf.len().is_multiple_of(ALIGN) {
75            let padding = ALIGN - (buf.len() % ALIGN);
76            buf.resize(buf.len() + padding, 0);
77        }
78
79        Ok(())
80    }
81
82    /// Decode the bytes from the buffer.
83    /// Reads the header to get the data offset and size, then read the actual data.
84    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
85        Ok(Self::from(read_bytes::<B, ALIGN, false>(buf, offset)?))
86    }
87
88    /// Partially decode the bytes from the buffer.
89    /// Returns the data offset and size without reading the actual data.
90    fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
91        read_bytes_header::<B, ALIGN, false>(buf, offset)
92    }
93}
94
95impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, true, false> for String {
96    const HEADER_SIZE: usize = <Bytes as Encoder<B, ALIGN, true, false>>::HEADER_SIZE;
97    const IS_DYNAMIC: bool = true;
98
99    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
100        <Bytes as Encoder<B, ALIGN, true, false>>::encode(
101            &Bytes::copy_from_slice(self.as_bytes()),
102            buf,
103            offset,
104        )
105    }
106
107    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
108        let bytes = <Bytes as Encoder<B, ALIGN, true, false>>::decode(buf, offset)?;
109        String::from_utf8(bytes.to_vec()).map_err(|_| {
110            CodecError::Decoding(DecodingError::InvalidData(
111                "failed to decode string from utf8".to_string(),
112            ))
113        })
114    }
115
116    fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
117        <Bytes as Encoder<B, ALIGN, true, false>>::partial_decode(buf, offset)
118    }
119}
120
121impl<B: ByteOrder, const ALIGN: usize> Encoder<B, ALIGN, false, false> for String {
122    const HEADER_SIZE: usize = <Bytes as Encoder<B, ALIGN, false, false>>::HEADER_SIZE;
123    const IS_DYNAMIC: bool = true;
124
125    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
126        <Bytes as Encoder<B, ALIGN, false, false>>::encode(
127            &Bytes::copy_from_slice(self.as_bytes()),
128            buf,
129            offset,
130        )
131    }
132
133    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
134        let bytes = <Bytes as Encoder<B, ALIGN, false, false>>::decode(buf, offset)?;
135        String::from_utf8(bytes.to_vec()).map_err(|_| {
136            CodecError::Decoding(DecodingError::InvalidData(
137                "failed to decode string from utf8".to_string(),
138            ))
139        })
140    }
141
142    fn partial_decode(buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
143        <Bytes as Encoder<B, ALIGN, false, false>>::partial_decode(buf, offset)
144    }
145}
146
147impl<const N: usize, B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
148    Encoder<B, ALIGN, false, IS_STATIC> for FixedBytes<N>
149{
150    const HEADER_SIZE: usize = N;
151    const IS_DYNAMIC: bool = false;
152
153    /// Encode the fixed bytes into the buffer.
154    /// Writes the fixed bytes directly to the buffer at the given offset.
155    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
156        let slice = get_aligned_slice::<B, ALIGN>(buf, offset, N);
157        slice.copy_from_slice(self.as_ref());
158        Ok(())
159    }
160
161    /// Decode the fixed bytes from the buffer.
162    /// Reads the fixed bytes directly from the buffer at the given offset.
163    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
164        if buf.remaining() < offset + N {
165            return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
166                expected: offset + N,
167                found: buf.remaining(),
168                msg: "Buffer too small to decode FixedBytes".to_string(),
169            }));
170        }
171        let data = buf.chunk()[offset..offset + N].to_vec();
172        Ok(FixedBytes::from_slice(&data))
173    }
174
175    /// Partially decode the fixed bytes from the buffer.
176    /// Returns the data offset and size without reading the actual data.
177    fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
178        let aligned_offset = align_up::<ALIGN>(offset);
179        Ok((aligned_offset, N))
180    }
181}
182
183impl<const N: usize, B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
184    Encoder<B, ALIGN, true, IS_STATIC> for FixedBytes<N>
185{
186    const HEADER_SIZE: usize = 32; // Always 32 bytes for Solidity ABI
187    const IS_DYNAMIC: bool = false;
188
189    /// Encode the fixed bytes into the buffer for Solidity mode.
190    /// Writes the fixed bytes directly to the buffer at the given offset, zero-padding to 32 bytes.
191    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
192        let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
193        slice[..N].copy_from_slice(self.as_ref());
194        // Zero-pad the rest
195        slice[N..].fill(0);
196        Ok(())
197    }
198
199    /// Decode the fixed bytes from the buffer for Solidity mode.
200    /// Reads the fixed bytes directly from the buffer at the given offset, assuming 32-byte
201    /// alignment.
202    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
203        let offset = align_up::<32>(offset); // Always 32-byte aligned for Solidity
204        if buf.remaining() < offset + 32 {
205            return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
206                expected: offset + 32,
207                found: buf.remaining(),
208                msg: "Buffer too small to decode FixedBytes".to_string(),
209            }));
210        }
211        let data = buf.chunk()[offset..offset + N].to_vec();
212        Ok(FixedBytes::from_slice(&data))
213    }
214
215    /// Partially decode the fixed bytes from the buffer for Solidity mode.
216    /// Returns the data offset and size without reading the actual data.
217    fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
218        Ok((offset, 32))
219    }
220}
221
222macro_rules! impl_evm_fixed {
223    ($type:ty) => {
224        impl<B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
225            Encoder<B, ALIGN, false, IS_STATIC> for $type
226        {
227            const HEADER_SIZE: usize = <$type>::len_bytes();
228            const IS_DYNAMIC: bool = false;
229
230            /// Encode the fixed bytes into the buffer.
231            /// Writes the fixed bytes directly to the buffer at the given offset.
232            fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
233                let slice = get_aligned_slice::<B, ALIGN>(buf, offset, <$type>::len_bytes());
234                slice.copy_from_slice(self.as_ref());
235                Ok(())
236            }
237
238            /// Decode the fixed bytes from the buffer.
239            /// Reads the fixed bytes directly from the buffer at the given offset.
240            fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
241                let size = <$type>::len_bytes();
242                if buf.remaining() < offset + size {
243                    return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
244                        expected: offset + size,
245                        found: buf.remaining(),
246                        msg: "Buffer too small to decode fixed bytes".to_string(),
247                    }));
248                }
249                let data = buf.chunk()[offset..offset + size].to_vec();
250                Ok(<$type>::from_slice(&data))
251            }
252
253            /// Partially decode the fixed bytes from the buffer.
254            /// Returns the data offset and size without reading the actual data.
255            fn partial_decode(
256                _buf: &impl Buf,
257                offset: usize,
258            ) -> Result<(usize, usize), CodecError> {
259                Ok((offset, <$type>::len_bytes()))
260            }
261        }
262
263        impl<B: ByteOrder, const ALIGN: usize, const IS_STATIC: bool>
264            Encoder<B, ALIGN, true, IS_STATIC> for $type
265        {
266            const HEADER_SIZE: usize = 32; // Always 32 bytes for Solidity ABI
267            const IS_DYNAMIC: bool = false;
268
269            /// Encode the fixed bytes into the buffer for Solidity mode.
270            /// Writes the fixed bytes directly to the buffer at the given offset, zero-padding to
271            /// 32 bytes.
272            fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
273                let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
274                let size = <$type>::len_bytes();
275                // Zero-pad the beginning
276                slice[..32 - size].fill(0);
277                // Copy the address bytes to the end
278                slice[32 - size..].copy_from_slice(self.as_ref());
279                Ok(())
280            }
281
282            /// Decode the fixed bytes from the buffer for Solidity mode.
283            /// Reads the fixed bytes directly from the buffer at the given offset, assuming 32-byte
284            /// alignment.
285            fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
286                let size = <$type>::len_bytes();
287                if buf.remaining() < offset + 32 {
288                    return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
289                        expected: offset + 32,
290                        found: buf.remaining(),
291                        msg: "Buffer too small to decode fixed bytes".to_string(),
292                    }));
293                }
294                let data = buf.chunk()[offset + 32 - size..offset + 32].to_vec();
295                Ok(<$type>::from_slice(&data))
296            }
297
298            /// Partially decode the fixed bytes from the buffer for Solidity mode.
299            /// Returns the data offset and size without reading the actual data.
300            fn partial_decode(
301                _buf: &impl Buf,
302                offset: usize,
303            ) -> Result<(usize, usize), CodecError> {
304                Ok((offset, 32))
305            }
306        }
307    };
308}
309
310impl_evm_fixed!(Address);
311
312impl<
313        const BITS: usize,
314        const LIMBS: usize,
315        B: ByteOrder,
316        const ALIGN: usize,
317        const IS_STATIC: bool,
318    > Encoder<B, ALIGN, false, IS_STATIC> for Uint<BITS, LIMBS>
319{
320    const HEADER_SIZE: usize = Self::BYTES;
321    const IS_DYNAMIC: bool = false;
322
323    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
324        let word_size = align_up::<ALIGN>(Self::BYTES);
325
326        let slice = get_aligned_slice::<B, ALIGN>(buf, offset, word_size);
327
328        let bytes = if is_big_endian::<B>() {
329            self.to_be_bytes_vec()
330        } else {
331            self.to_le_bytes_vec()
332        };
333
334        slice[..Self::BYTES].copy_from_slice(&bytes);
335
336        Ok(())
337    }
338
339    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
340        let word_size = align_up::<ALIGN>(Self::BYTES);
341
342        if buf.remaining() < offset + word_size {
343            return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
344                expected: offset + word_size,
345                found: buf.remaining(),
346                msg: "buf too small to read Uint".to_string(),
347            }));
348        }
349
350        let chunk = &buf.chunk()[offset..offset + word_size];
351        let value_slice = &chunk[..Self::BYTES];
352
353        let value = if is_big_endian::<B>() {
354            Self::from_be_slice(value_slice)
355        } else {
356            Self::from_le_slice(value_slice)
357        };
358
359        Ok(value)
360    }
361
362    fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
363        let word_size = align_up::<ALIGN>(Self::BYTES);
364        Ok((offset, word_size))
365    }
366}
367
368impl<
369        const BITS: usize,
370        const LIMBS: usize,
371        B: ByteOrder,
372        const ALIGN: usize,
373        const IS_STATIC: bool,
374    > Encoder<B, ALIGN, true, IS_STATIC> for Uint<BITS, LIMBS>
375{
376    const HEADER_SIZE: usize = 32; // Always 32 bytes for Solidity ABI
377    const IS_DYNAMIC: bool = false;
378
379    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
380        let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
381
382        let bytes = if is_big_endian::<B>() {
383            self.to_be_bytes_vec()
384        } else {
385            self.to_le_bytes_vec()
386        };
387
388        // For Solidity ABI, right-align the data
389        slice[32 - Self::BYTES..].copy_from_slice(&bytes);
390        slice[..32 - Self::BYTES].fill(0); // Zero-pad the rest
391
392        Ok(())
393    }
394
395    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
396        if buf.remaining() < offset + 32 {
397            return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
398                expected: offset + 32,
399                found: buf.remaining(),
400                msg: "buf too small to read Uint".to_string(),
401            }));
402        }
403
404        let chunk = &buf.chunk()[offset..offset + 32];
405        let value_slice = &chunk[32 - Self::BYTES..];
406
407        let value = if is_big_endian::<B>() {
408            Self::from_be_slice(value_slice)
409        } else {
410            Self::from_le_slice(value_slice)
411        };
412
413        Ok(value)
414    }
415
416    fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
417        Ok((offset, 32))
418    }
419}
420
421impl<
422        const BITS: usize,
423        const LIMBS: usize,
424        B: ByteOrder,
425        const ALIGN: usize,
426        const IS_STATIC: bool,
427    > Encoder<B, ALIGN, false, IS_STATIC> for Signed<BITS, LIMBS>
428{
429    const HEADER_SIZE: usize = Self::BYTES;
430    const IS_DYNAMIC: bool = false;
431
432    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
433        let word_size = align_up::<ALIGN>(Self::BYTES);
434
435        let slice = get_aligned_slice::<B, ALIGN>(buf, offset, word_size);
436
437        let bytes = if is_big_endian::<B>() {
438            self.into_raw().to_be_bytes_vec()
439        } else {
440            self.into_raw().to_le_bytes_vec()
441        };
442
443        slice[..Self::BYTES].copy_from_slice(&bytes);
444
445        Ok(())
446    }
447
448    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
449        let word_size = align_up::<ALIGN>(Self::BYTES);
450
451        if buf.remaining() < offset + word_size {
452            return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
453                expected: offset + word_size,
454                found: buf.remaining(),
455                msg: "buf too small to read Signed".to_string(),
456            }));
457        }
458
459        let chunk = &buf.chunk()[offset..offset + word_size];
460        let value_slice = &chunk[..Self::BYTES];
461
462        let value = if is_big_endian::<B>() {
463            Self::from_raw(Uint::<BITS, LIMBS>::from_be_slice(value_slice))
464        } else {
465            Self::from_raw(Uint::<BITS, LIMBS>::from_le_slice(value_slice))
466        };
467
468        Ok(value)
469    }
470
471    fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
472        let word_size = align_up::<ALIGN>(Self::BYTES);
473        Ok((offset, word_size))
474    }
475}
476
477impl<
478        const BITS: usize,
479        const LIMBS: usize,
480        B: ByteOrder,
481        const ALIGN: usize,
482        const IS_STATIC: bool,
483    > Encoder<B, ALIGN, true, IS_STATIC> for Signed<BITS, LIMBS>
484{
485    const HEADER_SIZE: usize = 32; // Always 32 bytes for Solidity ABI
486    const IS_DYNAMIC: bool = false;
487
488    fn encode(&self, buf: &mut BytesMut, offset: usize) -> Result<(), CodecError> {
489        let slice = get_aligned_slice::<B, 32>(buf, offset, 32);
490
491        let bytes = if is_big_endian::<B>() {
492            self.into_raw().to_be_bytes_vec()
493        } else {
494            self.into_raw().to_le_bytes_vec()
495        };
496
497        // For Solidity ABI, right-align the data
498        slice[32 - Self::BYTES..].copy_from_slice(&bytes);
499
500        // For signed integers, we need to sign-extend the value
501        // If the most significant bit of the value is set (negative number),
502        // fill the padding with 1s, otherwise fill with 0s
503        if self.is_negative() {
504            slice[..32 - Self::BYTES].fill(0xFF);
505        } else {
506            slice[..32 - Self::BYTES].fill(0);
507        }
508
509        Ok(())
510    }
511
512    fn decode(buf: &impl Buf, offset: usize) -> Result<Self, CodecError> {
513        if buf.remaining() < offset + 32 {
514            return Err(CodecError::Decoding(DecodingError::BufferTooSmall {
515                expected: offset + 32,
516                found: buf.remaining(),
517                msg: "buf too small to read Signed".to_string(),
518            }));
519        }
520
521        let chunk = &buf.chunk()[offset..offset + 32];
522        let value_slice = &chunk[32 - Self::BYTES..];
523
524        let value = if is_big_endian::<B>() {
525            Self::from_raw(Uint::<BITS, LIMBS>::from_be_slice(value_slice))
526        } else {
527            Self::from_raw(Uint::<BITS, LIMBS>::from_le_slice(value_slice))
528        };
529
530        Ok(value)
531    }
532
533    fn partial_decode(_buf: &impl Buf, offset: usize) -> Result<(usize, usize), CodecError> {
534        Ok((offset, 32))
535    }
536}
537
538#[cfg(test)]
539mod tests {
540    use super::*;
541    use crate::{
542        byteorder::{BE, LE},
543        CompactABI,
544        SolidityABI,
545    };
546    #[cfg(test)]
547    use alloy_primitives::{Address, U256};
548    use alloy_primitives::{I128, I256};
549    use byteorder::{BigEndian, LittleEndian};
550    use bytes::BytesMut;
551
552    #[test]
553    fn test_write_to_existing_buf() {
554        let existing_data = &[
555            0, 0, 0, 0, 0, 0, 0, 32, // offset of the 1st bytes
556            0, 0, 0, 0, 0, 0, 0, 12, // length of the 1st bytes
557            0, 0, 0, 0, 0, 0, 0, 0, //
558            0, 0, 0, 0, 0, 0, 0, 0, //
559            72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, // b"Hello, World"
560        ];
561        let mut buf = BytesMut::new();
562        buf.extend_from_slice(existing_data);
563
564        let original = Bytes::from_static(b"Hello, World");
565        // Write the data to the buf
566        let _result =
567            write_bytes::<BigEndian, 8, false>(&mut buf, 16, &original, original.len() as u32);
568
569        let expected = [
570            0, 0, 0, 0, 0, 0, 0, 32, // offset of the 1st bytes
571            0, 0, 0, 0, 0, 0, 0, 12, // length of the 1st bytes
572            0, 0, 0, 0, 0, 0, 0, 44, // offset of the 2nd bytes
573            0, 0, 0, 0, 0, 0, 0, 12, // length of the 2nd bytes
574            72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, // b"Hello, World"
575            72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, // b"Hello, World"
576        ];
577
578        assert_eq!(buf.to_vec(), expected);
579
580        let encoded = buf.freeze();
581        println!("Encoded Bytes: {:?}", encoded.to_vec());
582
583        let decoded = read_bytes::<BigEndian, 8, false>(&encoded, 0).unwrap();
584
585        println!("Decoded Bytes: {:?}", decoded.to_vec());
586        assert_eq!(decoded.to_vec(), original.to_vec());
587    }
588
589    #[test]
590    fn test_address_encode_decode() {
591        let original = Address::from([0x42; 20]);
592        let mut buf = BytesMut::new();
593
594        <Address as Encoder<LittleEndian, 1, false, true>>::encode(&original, &mut buf, 0).unwrap();
595
596        let encoded = buf.freeze();
597        println!("Encoded Address: {}", hex::encode(&encoded));
598
599        let decoded =
600            <Address as Encoder<LittleEndian, 1, false, true>>::decode(&encoded, 0).unwrap();
601
602        assert_eq!(original, decoded);
603    }
604    #[test]
605    fn test_address_encode_decode_aligned() {
606        let original = Address::from([0x42; 20]);
607        let mut buf = BytesMut::new();
608
609        <Address as Encoder<LittleEndian, 32, true, true>>::encode(&original, &mut buf, 0).unwrap();
610
611        let encoded = buf.freeze();
612        println!("Encoded Address: {}", hex::encode(&encoded));
613
614        let decoded =
615            <Address as Encoder<LittleEndian, 32, true, true>>::decode(&encoded, 0).unwrap();
616
617        assert_eq!(original, decoded);
618    }
619
620    #[test]
621    fn test_uint_encode_decode_le() {
622        let original = U256::from(0x1234567890abcdef_u64);
623        let mut buf = BytesMut::new();
624
625        <U256 as Encoder<LittleEndian, 4, false, true>>::encode(&original, &mut buf, 0).unwrap();
626
627        let encoded = buf.freeze();
628        println!("Encoded U256 (LE): {}", hex::encode(&encoded));
629        let expected_encoded = "efcdab9078563412000000000000000000000000000000000000000000000000";
630        assert_eq!(hex::encode(&encoded), expected_encoded);
631
632        let decoded = <U256 as Encoder<LittleEndian, 4, false, true>>::decode(&encoded, 0).unwrap();
633
634        assert_eq!(original, decoded);
635    }
636
637    #[test]
638    fn test_uint_encode_decode_be() {
639        let original = U256::from(0x1234567890abcdef_u64);
640        let mut buf = BytesMut::new();
641
642        <U256 as Encoder<BigEndian, 4, false, true>>::encode(&original, &mut buf, 0).unwrap();
643
644        let encoded = buf.freeze();
645        println!("Encoded U256 (BE): {}", hex::encode(&encoded));
646        let expected_encoded = "0000000000000000000000000000000000000000000000001234567890abcdef";
647        assert_eq!(hex::encode(&encoded), expected_encoded);
648
649        let decoded = <U256 as Encoder<BigEndian, 4, false, true>>::decode(&encoded, 0).unwrap();
650
651        assert_eq!(original, decoded);
652    }
653    #[test]
654    fn test_string_encoding_solidity() {
655        let original = "Hello, World!!".to_string();
656        let mut buf = BytesMut::new();
657        <String as Encoder<BigEndian, 32, true, false>>::encode(&original, &mut buf, 0).unwrap();
658
659        let encoded = buf.freeze();
660
661        println!("Encoded String: {}", hex::encode(&encoded));
662
663        let expected_encoded = "0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000e48656c6c6f2c20576f726c642121000000000000000000000000000000000000";
664
665        assert_eq!(hex::encode(&encoded), expected_encoded);
666
667        let decoded = <String as Encoder<BigEndian, 32, true, false>>::decode(&encoded, 0).unwrap();
668
669        assert_eq!(original, decoded);
670    }
671    #[test]
672    fn test_string_encoding_fluent() {
673        let original = "Hello, World!!".to_string();
674        let mut buf = BytesMut::new();
675        <String as Encoder<LittleEndian, 4, false, false>>::encode(&original, &mut buf, 0).unwrap();
676
677        let encoded = buf.freeze();
678
679        println!("Encoded String: {}", hex::encode(&encoded));
680
681        let expected_encoded = "080000000e00000048656c6c6f2c20576f726c6421210000";
682
683        assert_eq!(hex::encode(&encoded), expected_encoded);
684
685        let decoded =
686            <String as Encoder<LittleEndian, 4, false, false>>::decode(&encoded, 0).unwrap();
687
688        assert_eq!(original, decoded);
689    }
690
691    #[test]
692    fn test_i128_solidity() {
693        // Test cases with expected encodings
694        let test_cases = [
695            // Simple positive number
696            (
697                I128::try_from(42i32).unwrap(),
698                "000000000000000000000000000000000000000000000000000000000000002a",
699            ),
700            // Simple negative number
701            (
702                I128::try_from(-42i32).unwrap(),
703                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6",
704            ),
705            // Zero
706            (
707                I128::try_from(0i32).unwrap(),
708                "0000000000000000000000000000000000000000000000000000000000000000",
709            ),
710            // Negative one (-1)
711            (
712                I128::try_from(-1i32).unwrap(),
713                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
714            ),
715            // Edge case: Maximum value (I128::MAX)
716            (
717                I128::MAX,
718                "000000000000000000000000000000007fffffffffffffffffffffffffffffff",
719            ),
720            // Edge case: Minimum value (I128::MIN)
721            (
722                I128::MIN,
723                "ffffffffffffffffffffffffffffffff80000000000000000000000000000000",
724            ),
725        ];
726
727        // Test each case
728        for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
729            println!(
730                "Testing I128 encoding/decoding for case {}; {}",
731                i, test_value
732            );
733            // Encode the value
734            let mut buf = BytesMut::new();
735            SolidityABI::encode(test_value, &mut buf, 0).unwrap();
736            let encoded = buf.freeze();
737
738            // Verify encoding matches expected value
739            let expected_encoded = hex::decode(expected_hex).unwrap();
740            assert_eq!(
741                encoded.to_vec(),
742                expected_encoded,
743                "Case {}: I128 encoding doesn't match expected value",
744                i
745            );
746
747            // Verify round-trip encoding/decoding
748            let decoded = SolidityABI::<I128>::decode(&encoded, 0).unwrap();
749            assert_eq!(
750                decoded, *test_value,
751                "Case {}: Round-trip encoding/decoding failed",
752                i
753            );
754        }
755    }
756
757    #[test]
758    fn test_i256_solidity() {
759        // Test cases with expected encodings
760        let test_cases = [
761            // Simple positive number
762            (
763                I256::try_from(42i32).unwrap(),
764                "000000000000000000000000000000000000000000000000000000000000002a",
765            ),
766            // Simple negative number
767            (
768                I256::try_from(-42i32).unwrap(),
769                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd6",
770            ),
771            // Zero
772            (
773                I256::try_from(0i32).unwrap(),
774                "0000000000000000000000000000000000000000000000000000000000000000",
775            ),
776            // Large positive number
777            (
778                I256::try_from(1234567890i64).unwrap(),
779                "00000000000000000000000000000000000000000000000000000000499602d2",
780            ),
781            // Large negative number
782            (
783                I256::try_from(-1234567890i64).unwrap(),
784                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffb669fd2e",
785            ),
786            // Edge case: Maximum value (I256::MAX)
787            (
788                I256::MAX,
789                "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
790            ),
791            // Edge case: Minimum value (I256::MIN)
792            (
793                I256::MIN,
794                "8000000000000000000000000000000000000000000000000000000000000000",
795            ),
796            // Edge case: Close to maximum (I256::MAX - 1)
797            (
798                I256::MAX - I256::ONE,
799                "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe",
800            ),
801            // Edge case: Close to minimum (I256::MIN + 1)
802            (
803                I256::MIN + I256::ONE,
804                "8000000000000000000000000000000000000000000000000000000000000001",
805            ),
806        ];
807
808        // Test each case
809        for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
810            println!(
811                "Testing I256 encoding/decoding for case {}; {}",
812                i, test_value
813            );
814            // Encode the value
815            let mut buf = BytesMut::new();
816            SolidityABI::encode(test_value, &mut buf, 0).unwrap();
817            let encoded = buf.freeze();
818
819            // Verify encoding matches expected value
820            let expected_encoded = hex::decode(expected_hex).unwrap();
821            assert_eq!(
822                encoded.to_vec(),
823                expected_encoded,
824                "Case {}: I256 encoding doesn't match expected value",
825                i
826            );
827
828            // Verify round-trip encoding/decoding
829            let decoded = SolidityABI::<I256>::decode(&encoded, 0).unwrap();
830            assert_eq!(
831                decoded, *test_value,
832                "Case {}: Round-trip encoding/decoding failed",
833                i
834            );
835        }
836    }
837
838    #[test]
839    fn test_i128_compact() {
840        // Test cases with expected encodings
841        // For CompactABI, I128 is encoded as 16 bytes in little-endian order
842        let test_cases = [
843            // Simple positive number
844            (
845                I128::try_from(42i32).unwrap(),
846                "2a000000000000000000000000000000",
847            ),
848            // Simple negative number
849            (
850                I128::try_from(-42i32).unwrap(),
851                "d6ffffffffffffffffffffffffffffff",
852            ),
853            // Zero
854            (
855                I128::try_from(0i32).unwrap(),
856                "00000000000000000000000000000000",
857            ),
858            // Negative one (-1)
859            (
860                I128::try_from(-1i32).unwrap(),
861                "ffffffffffffffffffffffffffffffff",
862            ),
863            // Edge case: Maximum value (I128::MAX)
864            (I128::MAX, "ffffffffffffffffffffffffffffff7f"),
865            // Edge case: Minimum value (I128::MIN)
866            (I128::MIN, "00000000000000000000000000000080"),
867        ];
868
869        // Test each case
870        for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
871            println!(
872                "Testing I128 CompactABI encoding/decoding for case {}; {}",
873                i, test_value
874            );
875            // Encode the value
876            let mut buf = BytesMut::new();
877            CompactABI::encode(test_value, &mut buf, 0).unwrap();
878            let encoded = buf.freeze();
879
880            // Verify encoding matches expected value
881            let expected_encoded = hex::decode(expected_hex).unwrap();
882            assert_eq!(
883                encoded.to_vec(),
884                expected_encoded,
885                "Case {}: I128 CompactABI encoding doesn't match expected value",
886                i
887            );
888
889            // Verify round-trip encoding/decoding
890            let decoded = CompactABI::<I128>::decode(&encoded, 0).unwrap();
891            assert_eq!(
892                decoded, *test_value,
893                "Case {}: CompactABI round-trip encoding/decoding failed",
894                i
895            );
896        }
897    }
898
899    #[test]
900    fn test_i256_compact() {
901        // Test cases with expected encodings
902        // For CompactABI, I256 uses little-endian byte order with 4-byte alignment
903        let test_cases = [
904            // Simple positive number
905            (
906                I256::try_from(42i32).unwrap(),
907                "2a00000000000000000000000000000000000000000000000000000000000000",
908            ),
909            // Simple negative number
910            (
911                I256::try_from(-42i32).unwrap(),
912                "d6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
913            ),
914            // Zero
915            (
916                I256::try_from(0i32).unwrap(),
917                "0000000000000000000000000000000000000000000000000000000000000000",
918            ),
919            // Large positive number
920            (
921                I256::try_from(1234567890i64).unwrap(),
922                "d202964900000000000000000000000000000000000000000000000000000000",
923            ),
924            // Large negative number
925            (
926                I256::try_from(-1234567890i64).unwrap(),
927                "2efd69b6ffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
928            ),
929            // Edge case: Maximum value (I256::MAX)
930            (
931                I256::MAX,
932                "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
933            ),
934            // Edge case: Minimum value (I256::MIN)
935            (
936                I256::MIN,
937                "0000000000000000000000000000000000000000000000000000000000000080",
938            ),
939        ];
940
941        // Test each case
942        for (i, (test_value, expected_hex)) in test_cases.iter().enumerate() {
943            println!(
944                "Testing I256 CompactABI encoding/decoding for case {}; {}",
945                i, test_value
946            );
947            // Encode the value
948            let mut buf = BytesMut::new();
949            CompactABI::encode(test_value, &mut buf, 0).unwrap();
950            let encoded = buf.freeze();
951
952            // Verify encoding matches expected value
953            let expected_encoded = hex::decode(expected_hex).unwrap();
954            assert_eq!(
955                encoded.to_vec(),
956                expected_encoded,
957                "Case {}: I256 CompactABI encoding doesn't match expected value",
958                i
959            );
960
961            // Verify round-trip encoding/decoding
962            let decoded = CompactABI::<I256>::decode(&encoded, 0).unwrap();
963            assert_eq!(
964                decoded, *test_value,
965                "Case {}: CompactABI round-trip encoding/decoding failed",
966                i
967            );
968        }
969    }
970
971    #[test]
972    fn test_i256_error_conditions() {
973        // Test decoding from a buffer that's too small
974        let too_small_buffer = BytesMut::new().freeze();
975        let result = SolidityABI::<I256>::decode(&too_small_buffer, 0);
976        assert!(result.is_err(), "Decoding from an empty buffer should fail");
977
978        // Test decoding from a buffer that's smaller than required
979        let small_buffer = BytesMut::from(&[0u8; 16][..]).freeze();
980        let result = SolidityABI::<I256>::decode(&small_buffer, 0);
981        assert!(
982            result.is_err(),
983            "Decoding from a buffer smaller than 32 bytes should fail"
984        );
985
986        // Test decoding with an offset that would cause reading beyond the buffer
987        // (but not overflow)
988        let buffer = BytesMut::from(&[0u8; 32][..]).freeze();
989        let result = SolidityABI::<I256>::decode(&buffer, 1); // Just 1 byte offset is enough to cause an error
990        assert!(
991            result.is_err(),
992            "Decoding with an offset that would read beyond buffer should fail"
993        );
994
995        // Test CompactABI decoding from a buffer that's too small
996        let too_small_buffer = BytesMut::new().freeze();
997        let result = CompactABI::<I256>::decode(&too_small_buffer, 0);
998        assert!(
999            result.is_err(),
1000            "CompactABI decoding from an empty buffer should fail"
1001        );
1002    }
1003}