Skip to main content

alloy_sol_types/types/
value.rs

1use super::SolType;
2use crate::{
3    Result, Word,
4    abi::{AbiDecoderConfig, TokenSeq},
5    private::SolTypeValue,
6    sol_data::{self, ByteCount, SupportedFixedBytes},
7};
8use alloc::{string::String, vec::Vec};
9use alloy_primitives::{Address, Bytes, FixedBytes, Function, I256, U256, aliases::*};
10
11/// A Solidity value.
12///
13/// This is a convenience trait that re-exports the logic in [`SolType`] with
14/// less generic implementations so that they can be used as methods with `self`
15/// receivers.
16///
17/// See [`SolType`] for more information.
18///
19/// # Implementer's Guide
20///
21/// It should not be necessary to implement this trait manually. Instead, use
22/// the [`sol!`](crate::sol!) procedural macro to parse Solidity syntax into
23/// types that implement this trait.
24///
25/// # Examples
26///
27/// ```
28/// use alloy_sol_types::SolValue;
29///
30/// let my_values = ("hello", 0xdeadbeef_u32, true, [0x42_u8; 24]);
31/// let _ = my_values.abi_encode();
32/// let _ = my_values.abi_encode_packed();
33/// assert_eq!(my_values.sol_name(), "(string,uint32,bool,bytes24)");
34/// ```
35pub trait SolValue: SolTypeValue<Self::SolType> {
36    /// The Solidity type that this type corresponds to.
37    type SolType: SolType;
38
39    /// The name of the associated Solidity type.
40    ///
41    /// See [`SolType::SOL_NAME`] for more information.
42    #[inline]
43    fn sol_name(&self) -> &'static str {
44        Self::SolType::SOL_NAME
45    }
46
47    /// Tokenizes the given value into this type's token.
48    ///
49    /// See [`SolType::tokenize`] for more information.
50    #[inline]
51    fn tokenize(&self) -> <Self::SolType as SolType>::Token<'_> {
52        <Self as SolTypeValue<Self::SolType>>::stv_to_tokens(self)
53    }
54
55    /// Detokenize a value from the given token.
56    ///
57    /// See [`SolType::detokenize`] for more information.
58    #[inline]
59    fn detokenize(token: <Self::SolType as SolType>::Token<'_>) -> Self
60    where
61        Self: From<<Self::SolType as SolType>::RustType>,
62    {
63        Self::from(<Self::SolType as SolType>::detokenize(token))
64    }
65
66    /// Calculate the ABI-encoded size of the data.
67    ///
68    /// See [`SolType::abi_encoded_size`] for more information.
69    #[inline]
70    fn abi_encoded_size(&self) -> usize {
71        <Self as SolTypeValue<Self::SolType>>::stv_abi_encoded_size(self)
72    }
73
74    /// Encode this data according to EIP-712 `encodeData` rules, and hash it
75    /// if necessary.
76    ///
77    /// See [`SolType::eip712_data_word`] for more information.
78    #[inline]
79    fn eip712_data_word(&self) -> Word {
80        <Self as SolTypeValue<Self::SolType>>::stv_eip712_data_word(self)
81    }
82
83    /// Non-standard Packed Mode ABI encoding.
84    ///
85    /// See [`SolType::abi_encode_packed_to`] for more information.
86    #[inline]
87    fn abi_encode_packed_to(&self, out: &mut Vec<u8>) {
88        <Self as SolTypeValue<Self::SolType>>::stv_abi_encode_packed_to(self, out)
89    }
90
91    /// Non-standard Packed Mode ABI encoding.
92    ///
93    /// See [`SolType::abi_encode_packed`] for more information.
94    #[inline]
95    fn abi_encode_packed(&self) -> Vec<u8> {
96        let mut out = Vec::new();
97        <Self as SolTypeValue<Self::SolType>>::stv_abi_encode_packed_to(self, &mut out);
98        out
99    }
100
101    /// ABI-encodes the value.
102    ///
103    /// See [`SolType::abi_encode`] for more information.
104    #[inline]
105    fn abi_encode(&self) -> Vec<u8> {
106        Self::SolType::abi_encode(self)
107    }
108
109    /// Encodes an ABI sequence.
110    ///
111    /// See [`SolType::abi_encode_sequence`] for more information.
112    #[inline]
113    fn abi_encode_sequence(&self) -> Vec<u8>
114    where
115        for<'a> <Self::SolType as SolType>::Token<'a>: TokenSeq<'a>,
116    {
117        Self::SolType::abi_encode_sequence(self)
118    }
119
120    /// Encodes an ABI sequence suitable for function parameters.
121    ///
122    /// See [`SolType::abi_encode_params`] for more information.
123    #[inline]
124    fn abi_encode_params(&self) -> Vec<u8>
125    where
126        for<'a> <Self::SolType as SolType>::Token<'a>: TokenSeq<'a>,
127    {
128        Self::SolType::abi_encode_params(self)
129    }
130
131    /// ABI-decode this type from the given data.
132    ///
133    /// See [`SolType::abi_decode`] for more information.
134    fn abi_decode(data: &[u8]) -> Result<Self>
135    where
136        Self: From<<Self::SolType as SolType>::RustType>,
137    {
138        Self::SolType::abi_decode(data).map(Self::from)
139    }
140
141    /// ABI-decode this type with a custom decoder configuration.
142    fn abi_decode_with_config(data: &[u8], config: AbiDecoderConfig) -> Result<Self>
143    where
144        Self: From<<Self::SolType as SolType>::RustType>,
145    {
146        Self::SolType::abi_decode_with_config(data, config).map(Self::from)
147    }
148
149    /// ABI-decode this type from the given data, with validation.
150    ///
151    /// See [`SolType::abi_decode_validate`] for more information.
152    // TODO: Deprecate in favor of a validating decoder configuration.
153    // #[deprecated(note = "use a validating decoder configuration")]
154    fn abi_decode_validate(data: &[u8]) -> Result<Self>
155    where
156        Self: From<<Self::SolType as SolType>::RustType>,
157    {
158        Self::abi_decode_with_config(data, AbiDecoderConfig::new().validate(true))
159    }
160
161    /// ABI-decode this type from the given data.
162    ///
163    /// See [`SolType::abi_decode_params`] for more information.
164    #[inline]
165    fn abi_decode_params<'de>(data: &'de [u8]) -> Result<Self>
166    where
167        Self: From<<Self::SolType as SolType>::RustType>,
168        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
169    {
170        Self::SolType::abi_decode_params(data).map(Self::from)
171    }
172
173    /// ABI-decode this type's function parameters with a custom decoder configuration.
174    #[inline]
175    fn abi_decode_params_with_config<'de>(data: &'de [u8], config: AbiDecoderConfig) -> Result<Self>
176    where
177        Self: From<<Self::SolType as SolType>::RustType>,
178        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
179    {
180        Self::SolType::abi_decode_params_with_config(data, config).map(Self::from)
181    }
182
183    /// ABI-decode this type from the given data, with validation.
184    ///
185    /// See [`SolType::abi_decode_params_validate`] for more information.
186    #[inline]
187    // TODO: Deprecate in favor of a validating decoder configuration.
188    // #[deprecated(note = "use a validating decoder configuration")]
189    fn abi_decode_params_validate<'de>(data: &'de [u8]) -> Result<Self>
190    where
191        Self: From<<Self::SolType as SolType>::RustType>,
192        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
193    {
194        Self::abi_decode_params_with_config(data, AbiDecoderConfig::new().validate(true))
195    }
196
197    /// ABI-decode this type from the given data.
198    ///
199    /// See [`SolType::abi_decode_sequence`] for more information.
200    #[inline]
201    fn abi_decode_sequence<'de>(data: &'de [u8]) -> Result<Self>
202    where
203        Self: From<<Self::SolType as SolType>::RustType>,
204        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
205    {
206        Self::SolType::abi_decode_sequence(data).map(Self::from)
207    }
208
209    /// ABI-decode this type's sequence with a custom decoder configuration.
210    #[inline]
211    fn abi_decode_sequence_with_config<'de>(
212        data: &'de [u8],
213        config: AbiDecoderConfig,
214    ) -> Result<Self>
215    where
216        Self: From<<Self::SolType as SolType>::RustType>,
217        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
218    {
219        Self::SolType::abi_decode_sequence_with_config(data, config).map(Self::from)
220    }
221
222    /// ABI-decode this type from the given data, with validation.
223    ///
224    /// See [`SolType::abi_decode_sequence_validate`] for more information.
225    #[inline]
226    // TODO: Deprecate in favor of a validating decoder configuration.
227    // #[deprecated(note = "use a validating decoder configuration")]
228    fn abi_decode_sequence_validate<'de>(data: &'de [u8]) -> Result<Self>
229    where
230        Self: From<<Self::SolType as SolType>::RustType>,
231        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
232    {
233        Self::abi_decode_sequence_with_config(data, AbiDecoderConfig::new().validate(true))
234    }
235}
236
237macro_rules! impl_sol_value {
238    ($($(#[$attr:meta])* [$($gen:tt)*] $rust:ty => $sol:ty [$($where:tt)*];)+) => {$(
239        $(#[$attr])*
240        impl<$($gen)*> SolValue for $rust $($where)* {
241            type SolType = $sol;
242        }
243    )*};
244}
245
246impl_sol_value! {
247    // Basic
248    [] bool => sol_data::Bool [];
249
250    []   i8 => sol_data::Int::<8> [];
251    []  i16 => sol_data::Int::<16> [];
252    []  I24 => sol_data::Int::<24> [];
253    []  i32 => sol_data::Int::<32> [];
254    []  I40 => sol_data::Int::<40> [];
255    []  I48 => sol_data::Int::<48> [];
256    []  I56 => sol_data::Int::<56> [];
257    []  i64 => sol_data::Int::<64> [];
258    []  I72 => sol_data::Int::<72> [];
259    []  I80 => sol_data::Int::<80> [];
260    []  I88 => sol_data::Int::<88> [];
261    []  I96 => sol_data::Int::<96> [];
262    [] I104 => sol_data::Int::<104> [];
263    [] I112 => sol_data::Int::<112> [];
264    [] I120 => sol_data::Int::<120> [];
265    [] i128 => sol_data::Int::<128> [];
266    [] I136 => sol_data::Int::<136> [];
267    [] I144 => sol_data::Int::<144> [];
268    [] I152 => sol_data::Int::<152> [];
269    [] I160 => sol_data::Int::<160> [];
270    [] I168 => sol_data::Int::<168> [];
271    [] I176 => sol_data::Int::<176> [];
272    [] I184 => sol_data::Int::<184> [];
273    [] I192 => sol_data::Int::<192> [];
274    [] I200 => sol_data::Int::<200> [];
275    [] I208 => sol_data::Int::<208> [];
276    [] I216 => sol_data::Int::<216> [];
277    [] I224 => sol_data::Int::<224> [];
278    [] I232 => sol_data::Int::<232> [];
279    [] I240 => sol_data::Int::<240> [];
280    [] I248 => sol_data::Int::<248> [];
281    [] I256 => sol_data::Int::<256> [];
282
283    // TODO: `u8` is specialized to encode as `bytes` or `bytesN`
284    // [] u8 => sol_data::Uint::<8> [];
285    []  u16 => sol_data::Uint::<16> [];
286    []  U24 => sol_data::Uint::<24> [];
287    []  u32 => sol_data::Uint::<32> [];
288    []  U40 => sol_data::Uint::<40> [];
289    []  U48 => sol_data::Uint::<48> [];
290    []  U56 => sol_data::Uint::<56> [];
291    []  u64 => sol_data::Uint::<64> [];
292    []  U72 => sol_data::Uint::<72> [];
293    []  U80 => sol_data::Uint::<80> [];
294    []  U88 => sol_data::Uint::<88> [];
295    []  U96 => sol_data::Uint::<96> [];
296    [] U104 => sol_data::Uint::<104> [];
297    [] U112 => sol_data::Uint::<112> [];
298    [] U120 => sol_data::Uint::<120> [];
299    [] u128 => sol_data::Uint::<128> [];
300    [] U136 => sol_data::Uint::<136> [];
301    [] U144 => sol_data::Uint::<144> [];
302    [] U152 => sol_data::Uint::<152> [];
303    [] U160 => sol_data::Uint::<160> [];
304    [] U168 => sol_data::Uint::<168> [];
305    [] U176 => sol_data::Uint::<176> [];
306    [] U184 => sol_data::Uint::<184> [];
307    [] U192 => sol_data::Uint::<192> [];
308    [] U200 => sol_data::Uint::<200> [];
309    [] U208 => sol_data::Uint::<208> [];
310    [] U216 => sol_data::Uint::<216> [];
311    [] U224 => sol_data::Uint::<224> [];
312    [] U232 => sol_data::Uint::<232> [];
313    [] U240 => sol_data::Uint::<240> [];
314    [] U248 => sol_data::Uint::<248> [];
315    [] U256 => sol_data::Uint::<256> [];
316
317    [] Address => sol_data::Address [];
318    [] Function => sol_data::Function [];
319    [const N: usize] FixedBytes<N> => sol_data::FixedBytes<N> [where ByteCount<N>: SupportedFixedBytes];
320    [const N: usize] [u8; N] => sol_data::FixedBytes<N> [where ByteCount<N>: SupportedFixedBytes];
321
322    // `bytes` and `string` are specialized below.
323
324    // Generic
325    [T: SolValue] Vec<T> => sol_data::Array<T::SolType> [];
326    [T: SolValue] [T] => sol_data::Array<T::SolType> [];
327    [T: SolValue, const N: usize] [T; N] => sol_data::FixedArray<T::SolType, N> [];
328
329    ['a, T: ?Sized + SolValue] &'a T => T::SolType [where &'a T: SolTypeValue<T::SolType>];
330    ['a, T: ?Sized + SolValue] &'a mut T => T::SolType [where &'a mut T: SolTypeValue<T::SolType>];
331}
332
333macro_rules! tuple_impls {
334    ($count:literal $($ty:ident),+) => {
335        impl<$($ty: SolValue,)+> SolValue for ($($ty,)+) {
336            type SolType = ($($ty::SolType,)+);
337        }
338    };
339}
340
341impl SolValue for () {
342    type SolType = ();
343}
344
345all_the_tuples!(tuple_impls);
346
347// Empty `bytes` and `string` specialization
348impl SolValue for str {
349    type SolType = sol_data::String;
350
351    #[inline]
352    fn abi_encode(&self) -> Vec<u8> {
353        if self.is_empty() {
354            crate::abi::EMPTY_BYTES.to_vec()
355        } else {
356            <Self::SolType as SolType>::abi_encode(self)
357        }
358    }
359}
360
361impl SolValue for [u8] {
362    type SolType = sol_data::Bytes;
363
364    #[inline]
365    fn abi_encode(&self) -> Vec<u8> {
366        if self.is_empty() {
367            crate::abi::EMPTY_BYTES.to_vec()
368        } else {
369            <Self::SolType as SolType>::abi_encode(self)
370        }
371    }
372}
373
374impl SolValue for String {
375    type SolType = sol_data::String;
376
377    #[inline]
378    fn abi_encode(&self) -> Vec<u8> {
379        self[..].abi_encode()
380    }
381}
382
383impl SolValue for Bytes {
384    type SolType = sol_data::Bytes;
385
386    #[inline]
387    fn abi_encode(&self) -> Vec<u8> {
388        self[..].abi_encode()
389    }
390}
391
392impl SolValue for Vec<u8> {
393    type SolType = sol_data::Bytes;
394
395    #[inline]
396    fn abi_encode(&self) -> Vec<u8> {
397        self[..].abi_encode()
398    }
399}
400
401#[cfg(test)]
402#[allow(clippy::type_complexity)]
403mod tests {
404    use super::*;
405
406    // Make sure these are in scope
407    #[allow(unused_imports)]
408    use crate::{SolType as _, private::SolTypeValue as _};
409
410    #[test]
411    fn inference() {
412        false.sol_name();
413        false.abi_encoded_size();
414        false.eip712_data_word();
415        false.abi_encode_packed_to(&mut vec![]);
416        false.abi_encode_packed();
417        false.abi_encode();
418        (false,).abi_encode_sequence();
419        (false,).abi_encode_params();
420
421        "".sol_name();
422        "".abi_encoded_size();
423        "".eip712_data_word();
424        "".abi_encode_packed_to(&mut vec![]);
425        "".abi_encode_packed();
426        "".abi_encode();
427        ("",).abi_encode_sequence();
428        ("",).abi_encode_params();
429
430        let _ = String::abi_decode(b"");
431        let _ = bool::abi_decode(b"");
432    }
433
434    #[test]
435    fn basic() {
436        assert_eq!(false.abi_encode(), Word::ZERO[..]);
437        assert_eq!(true.abi_encode(), Word::with_last_byte(1)[..]);
438
439        assert_eq!(0i8.abi_encode(), Word::ZERO[..]);
440        assert_eq!(0i16.abi_encode(), Word::ZERO[..]);
441        assert_eq!(0i32.abi_encode(), Word::ZERO[..]);
442        assert_eq!(0i64.abi_encode(), Word::ZERO[..]);
443        assert_eq!(0i128.abi_encode(), Word::ZERO[..]);
444        assert_eq!(I256::ZERO.abi_encode(), Word::ZERO[..]);
445
446        assert_eq!(0u16.abi_encode(), Word::ZERO[..]);
447        assert_eq!(0u32.abi_encode(), Word::ZERO[..]);
448        assert_eq!(0u64.abi_encode(), Word::ZERO[..]);
449        assert_eq!(0u128.abi_encode(), Word::ZERO[..]);
450        assert_eq!(U256::ZERO.abi_encode(), Word::ZERO[..]);
451
452        assert_eq!(Address::ZERO.abi_encode(), Word::ZERO[..]);
453        assert_eq!(Function::ZERO.abi_encode(), Word::ZERO[..]);
454
455        let encode_bytes = |b: &[u8]| {
456            let last = Word::new({
457                let mut buf = [0u8; 32];
458                buf[..b.len()].copy_from_slice(b);
459                buf
460            });
461            [
462                &Word::with_last_byte(0x20)[..],
463                &Word::with_last_byte(b.len() as u8)[..],
464                if b.is_empty() { b } else { &last[..] },
465            ]
466            .concat()
467        };
468
469        // empty `bytes`
470        assert_eq!(b"".abi_encode(), encode_bytes(b""));
471        assert_eq!((b"" as &[_]).abi_encode(), encode_bytes(b""));
472        // `bytes1`
473        assert_eq!(b"a".abi_encode()[0], b'a');
474        assert_eq!(b"a".abi_encode()[1..], Word::ZERO[1..]);
475        // `bytes`
476        assert_eq!((b"a" as &[_]).abi_encode(), encode_bytes(b"a"));
477
478        assert_eq!("".abi_encode(), encode_bytes(b""));
479        assert_eq!("a".abi_encode(), encode_bytes(b"a"));
480        assert_eq!(String::new().abi_encode(), encode_bytes(b""));
481        assert_eq!(String::from("a").abi_encode(), encode_bytes(b"a"));
482        assert_eq!(Vec::<u8>::new().abi_encode(), encode_bytes(b""));
483        assert_eq!(Vec::<u8>::from(&b"a"[..]).abi_encode(), encode_bytes(b"a"));
484    }
485
486    #[test]
487    fn big() {
488        let tuple = (
489            false,
490            0i8,
491            0i16,
492            0i32,
493            0i64,
494            0i128,
495            I256::ZERO,
496            // 0u8,
497            0u16,
498            0u32,
499            0u64,
500            0u128,
501            U256::ZERO,
502            Address::ZERO,
503            Function::ZERO,
504        );
505        let encoded = tuple.abi_encode();
506        assert_eq!(encoded.len(), 32 * 14);
507        assert!(encoded.iter().all(|&b| b == 0));
508    }
509
510    #[test]
511    fn complex() {
512        let tuple = ((((((false,),),),),),);
513        assert_eq!(tuple.abi_encode(), Word::ZERO[..]);
514        assert_eq!(tuple.sol_name(), "((((((bool))))))");
515
516        let tuple = (
517            42u64,
518            "hello world",
519            true,
520            (
521                String::from("aaaa"),
522                Address::with_last_byte(69),
523                b"bbbb".to_vec(),
524                b"cccc",
525                &b"dddd"[..],
526            ),
527        );
528        assert_eq!(tuple.sol_name(), "(uint64,string,bool,(string,address,bytes,bytes4,bytes))");
529    }
530
531    #[test]
532    fn derefs() {
533        let x: &[Address; 0] = &[];
534        x.abi_encode();
535        assert_eq!(x.sol_name(), "address[0]");
536
537        let x = &[Address::ZERO];
538        x.abi_encode();
539        assert_eq!(x.sol_name(), "address[1]");
540
541        let x = &[Address::ZERO, Address::ZERO];
542        x.abi_encode();
543        assert_eq!(x.sol_name(), "address[2]");
544
545        let x = &[Address::ZERO][..];
546        x.abi_encode();
547        assert_eq!(x.sol_name(), "address[]");
548
549        let mut x = *b"0";
550        let x = (&mut x, *b"aaaa", b"00");
551        x.abi_encode();
552        assert_eq!(x.sol_name(), "(bytes1,bytes4,bytes2)");
553
554        let tuple = &(&0u16, &"", b"0", &mut [Address::ZERO][..]);
555        tuple.abi_encode();
556        assert_eq!(tuple.sol_name(), "(uint16,string,bytes1,address[])");
557    }
558
559    #[test]
560    fn decode() {
561        let _: Result<String> = String::abi_decode(b"");
562
563        let _: Result<Vec<String>> = Vec::<String>::abi_decode(b"");
564
565        let _: Result<(u64, String, U256)> = <(u64, String, U256)>::abi_decode(b"");
566        let _: Result<(i64, Vec<(u32, String, Vec<FixedBytes<4>>)>, U256)> =
567            <(i64, Vec<(u32, String, Vec<FixedBytes<4>>)>, U256)>::abi_decode(b"");
568    }
569
570    #[test]
571    fn empty_spec() {
572        assert_eq!("".abi_encode(), crate::abi::EMPTY_BYTES);
573        assert_eq!(b"".abi_encode(), crate::abi::EMPTY_BYTES);
574        assert_eq!(
575            ("", "a").abi_encode(),
576            <(sol_data::String, sol_data::String)>::abi_encode(&("", "a"))
577        );
578        assert_eq!(
579            ("a", "").abi_encode(),
580            <(sol_data::String, sol_data::String)>::abi_encode(&("a", ""))
581        );
582        assert_eq!(
583            (&b""[..], &b"a"[..]).abi_encode(),
584            <(sol_data::Bytes, sol_data::Bytes)>::abi_encode(&(b"", b"a"))
585        );
586        assert_eq!(
587            (&b"a"[..], &b""[..]).abi_encode(),
588            <(sol_data::Bytes, sol_data::Bytes)>::abi_encode(&(b"a", b""))
589        );
590    }
591}