alloy_sol_types/types/
value.rs

1use super::SolType;
2use crate::{
3    Result, Word,
4    abi::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 from the given data, with validation.
142    ///
143    /// See [`SolType::abi_decode_validate`] for more information.
144    fn abi_decode_validate(data: &[u8]) -> Result<Self>
145    where
146        Self: From<<Self::SolType as SolType>::RustType>,
147    {
148        Self::SolType::abi_decode_validate(data).map(Self::from)
149    }
150
151    /// ABI-decode this type from the given data.
152    ///
153    /// See [`SolType::abi_decode_params`] for more information.
154    #[inline]
155    fn abi_decode_params<'de>(data: &'de [u8]) -> Result<Self>
156    where
157        Self: From<<Self::SolType as SolType>::RustType>,
158        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
159    {
160        Self::SolType::abi_decode_params(data).map(Self::from)
161    }
162
163    /// ABI-decode this type from the given data, with validation.
164    ///
165    /// See [`SolType::abi_decode_params_validate`] for more information.
166    #[inline]
167    fn abi_decode_params_validate<'de>(data: &'de [u8]) -> Result<Self>
168    where
169        Self: From<<Self::SolType as SolType>::RustType>,
170        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
171    {
172        Self::SolType::abi_decode_params_validate(data).map(Self::from)
173    }
174
175    /// ABI-decode this type from the given data.
176    ///
177    /// See [`SolType::abi_decode_sequence`] for more information.
178    #[inline]
179    fn abi_decode_sequence<'de>(data: &'de [u8]) -> Result<Self>
180    where
181        Self: From<<Self::SolType as SolType>::RustType>,
182        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
183    {
184        Self::SolType::abi_decode_sequence(data).map(Self::from)
185    }
186
187    /// ABI-decode this type from the given data, with validation.
188    ///
189    /// See [`SolType::abi_decode_sequence_validate`] for more information.
190    #[inline]
191    fn abi_decode_sequence_validate<'de>(data: &'de [u8]) -> Result<Self>
192    where
193        Self: From<<Self::SolType as SolType>::RustType>,
194        <Self::SolType as SolType>::Token<'de>: TokenSeq<'de>,
195    {
196        Self::SolType::abi_decode_sequence_validate(data).map(Self::from)
197    }
198}
199
200macro_rules! impl_sol_value {
201    ($($(#[$attr:meta])* [$($gen:tt)*] $rust:ty => $sol:ty [$($where:tt)*];)+) => {$(
202        $(#[$attr])*
203        impl<$($gen)*> SolValue for $rust $($where)* {
204            type SolType = $sol;
205        }
206    )*};
207}
208
209impl_sol_value! {
210    // Basic
211    [] bool => sol_data::Bool [];
212
213    []   i8 => sol_data::Int::<8> [];
214    []  i16 => sol_data::Int::<16> [];
215    []  I24 => sol_data::Int::<24> [];
216    []  i32 => sol_data::Int::<32> [];
217    []  I40 => sol_data::Int::<40> [];
218    []  I48 => sol_data::Int::<48> [];
219    []  I56 => sol_data::Int::<56> [];
220    []  i64 => sol_data::Int::<64> [];
221    []  I72 => sol_data::Int::<72> [];
222    []  I80 => sol_data::Int::<80> [];
223    []  I88 => sol_data::Int::<88> [];
224    []  I96 => sol_data::Int::<96> [];
225    [] I104 => sol_data::Int::<104> [];
226    [] I112 => sol_data::Int::<112> [];
227    [] I120 => sol_data::Int::<120> [];
228    [] i128 => sol_data::Int::<128> [];
229    [] I136 => sol_data::Int::<136> [];
230    [] I144 => sol_data::Int::<144> [];
231    [] I152 => sol_data::Int::<152> [];
232    [] I160 => sol_data::Int::<160> [];
233    [] I168 => sol_data::Int::<168> [];
234    [] I176 => sol_data::Int::<176> [];
235    [] I184 => sol_data::Int::<184> [];
236    [] I192 => sol_data::Int::<192> [];
237    [] I200 => sol_data::Int::<200> [];
238    [] I208 => sol_data::Int::<208> [];
239    [] I216 => sol_data::Int::<216> [];
240    [] I224 => sol_data::Int::<224> [];
241    [] I232 => sol_data::Int::<232> [];
242    [] I240 => sol_data::Int::<240> [];
243    [] I248 => sol_data::Int::<248> [];
244    [] I256 => sol_data::Int::<256> [];
245
246    // TODO: `u8` is specialized to encode as `bytes` or `bytesN`
247    // [] u8 => sol_data::Uint::<8> [];
248    []  u16 => sol_data::Uint::<16> [];
249    []  U24 => sol_data::Uint::<24> [];
250    []  u32 => sol_data::Uint::<32> [];
251    []  U40 => sol_data::Uint::<40> [];
252    []  U48 => sol_data::Uint::<48> [];
253    []  U56 => sol_data::Uint::<56> [];
254    []  u64 => sol_data::Uint::<64> [];
255    []  U72 => sol_data::Uint::<72> [];
256    []  U80 => sol_data::Uint::<80> [];
257    []  U88 => sol_data::Uint::<88> [];
258    []  U96 => sol_data::Uint::<96> [];
259    [] U104 => sol_data::Uint::<104> [];
260    [] U112 => sol_data::Uint::<112> [];
261    [] U120 => sol_data::Uint::<120> [];
262    [] u128 => sol_data::Uint::<128> [];
263    [] U136 => sol_data::Uint::<136> [];
264    [] U144 => sol_data::Uint::<144> [];
265    [] U152 => sol_data::Uint::<152> [];
266    [] U160 => sol_data::Uint::<160> [];
267    [] U168 => sol_data::Uint::<168> [];
268    [] U176 => sol_data::Uint::<176> [];
269    [] U184 => sol_data::Uint::<184> [];
270    [] U192 => sol_data::Uint::<192> [];
271    [] U200 => sol_data::Uint::<200> [];
272    [] U208 => sol_data::Uint::<208> [];
273    [] U216 => sol_data::Uint::<216> [];
274    [] U224 => sol_data::Uint::<224> [];
275    [] U232 => sol_data::Uint::<232> [];
276    [] U240 => sol_data::Uint::<240> [];
277    [] U248 => sol_data::Uint::<248> [];
278    [] U256 => sol_data::Uint::<256> [];
279
280    [] Address => sol_data::Address [];
281    [] Function => sol_data::Function [];
282    [const N: usize] FixedBytes<N> => sol_data::FixedBytes<N> [where ByteCount<N>: SupportedFixedBytes];
283    [const N: usize] [u8; N] => sol_data::FixedBytes<N> [where ByteCount<N>: SupportedFixedBytes];
284
285    // `bytes` and `string` are specialized below.
286
287    // Generic
288    [T: SolValue] Vec<T> => sol_data::Array<T::SolType> [];
289    [T: SolValue] [T] => sol_data::Array<T::SolType> [];
290    [T: SolValue, const N: usize] [T; N] => sol_data::FixedArray<T::SolType, N> [];
291
292    ['a, T: ?Sized + SolValue] &'a T => T::SolType [where &'a T: SolTypeValue<T::SolType>];
293    ['a, T: ?Sized + SolValue] &'a mut T => T::SolType [where &'a mut T: SolTypeValue<T::SolType>];
294}
295
296macro_rules! tuple_impls {
297    ($count:literal $($ty:ident),+) => {
298        impl<$($ty: SolValue,)+> SolValue for ($($ty,)+) {
299            type SolType = ($($ty::SolType,)+);
300        }
301    };
302}
303
304impl SolValue for () {
305    type SolType = ();
306}
307
308all_the_tuples!(tuple_impls);
309
310// Empty `bytes` and `string` specialization
311impl SolValue for str {
312    type SolType = sol_data::String;
313
314    #[inline]
315    fn abi_encode(&self) -> Vec<u8> {
316        if self.is_empty() {
317            crate::abi::EMPTY_BYTES.to_vec()
318        } else {
319            <Self::SolType as SolType>::abi_encode(self)
320        }
321    }
322}
323
324impl SolValue for [u8] {
325    type SolType = sol_data::Bytes;
326
327    #[inline]
328    fn abi_encode(&self) -> Vec<u8> {
329        if self.is_empty() {
330            crate::abi::EMPTY_BYTES.to_vec()
331        } else {
332            <Self::SolType as SolType>::abi_encode(self)
333        }
334    }
335}
336
337impl SolValue for String {
338    type SolType = sol_data::String;
339
340    #[inline]
341    fn abi_encode(&self) -> Vec<u8> {
342        self[..].abi_encode()
343    }
344}
345
346impl SolValue for Bytes {
347    type SolType = sol_data::Bytes;
348
349    #[inline]
350    fn abi_encode(&self) -> Vec<u8> {
351        self[..].abi_encode()
352    }
353}
354
355impl SolValue for Vec<u8> {
356    type SolType = sol_data::Bytes;
357
358    #[inline]
359    fn abi_encode(&self) -> Vec<u8> {
360        self[..].abi_encode()
361    }
362}
363
364#[cfg(test)]
365#[allow(clippy::type_complexity)]
366mod tests {
367    use super::*;
368
369    // Make sure these are in scope
370    #[allow(unused_imports)]
371    use crate::{SolType as _, private::SolTypeValue as _};
372
373    #[test]
374    fn inference() {
375        false.sol_name();
376        false.abi_encoded_size();
377        false.eip712_data_word();
378        false.abi_encode_packed_to(&mut vec![]);
379        false.abi_encode_packed();
380        false.abi_encode();
381        (false,).abi_encode_sequence();
382        (false,).abi_encode_params();
383
384        "".sol_name();
385        "".abi_encoded_size();
386        "".eip712_data_word();
387        "".abi_encode_packed_to(&mut vec![]);
388        "".abi_encode_packed();
389        "".abi_encode();
390        ("",).abi_encode_sequence();
391        ("",).abi_encode_params();
392
393        let _ = String::abi_decode(b"");
394        let _ = bool::abi_decode(b"");
395    }
396
397    #[test]
398    fn basic() {
399        assert_eq!(false.abi_encode(), Word::ZERO[..]);
400        assert_eq!(true.abi_encode(), Word::with_last_byte(1)[..]);
401
402        assert_eq!(0i8.abi_encode(), Word::ZERO[..]);
403        assert_eq!(0i16.abi_encode(), Word::ZERO[..]);
404        assert_eq!(0i32.abi_encode(), Word::ZERO[..]);
405        assert_eq!(0i64.abi_encode(), Word::ZERO[..]);
406        assert_eq!(0i128.abi_encode(), Word::ZERO[..]);
407        assert_eq!(I256::ZERO.abi_encode(), Word::ZERO[..]);
408
409        assert_eq!(0u16.abi_encode(), Word::ZERO[..]);
410        assert_eq!(0u32.abi_encode(), Word::ZERO[..]);
411        assert_eq!(0u64.abi_encode(), Word::ZERO[..]);
412        assert_eq!(0u128.abi_encode(), Word::ZERO[..]);
413        assert_eq!(U256::ZERO.abi_encode(), Word::ZERO[..]);
414
415        assert_eq!(Address::ZERO.abi_encode(), Word::ZERO[..]);
416        assert_eq!(Function::ZERO.abi_encode(), Word::ZERO[..]);
417
418        let encode_bytes = |b: &[u8]| {
419            let last = Word::new({
420                let mut buf = [0u8; 32];
421                buf[..b.len()].copy_from_slice(b);
422                buf
423            });
424            [
425                &Word::with_last_byte(0x20)[..],
426                &Word::with_last_byte(b.len() as u8)[..],
427                if b.is_empty() { b } else { &last[..] },
428            ]
429            .concat()
430        };
431
432        // empty `bytes`
433        assert_eq!(b"".abi_encode(), encode_bytes(b""));
434        assert_eq!((b"" as &[_]).abi_encode(), encode_bytes(b""));
435        // `bytes1`
436        assert_eq!(b"a".abi_encode()[0], b'a');
437        assert_eq!(b"a".abi_encode()[1..], Word::ZERO[1..]);
438        // `bytes`
439        assert_eq!((b"a" as &[_]).abi_encode(), encode_bytes(b"a"));
440
441        assert_eq!("".abi_encode(), encode_bytes(b""));
442        assert_eq!("a".abi_encode(), encode_bytes(b"a"));
443        assert_eq!(String::new().abi_encode(), encode_bytes(b""));
444        assert_eq!(String::from("a").abi_encode(), encode_bytes(b"a"));
445        assert_eq!(Vec::<u8>::new().abi_encode(), encode_bytes(b""));
446        assert_eq!(Vec::<u8>::from(&b"a"[..]).abi_encode(), encode_bytes(b"a"));
447    }
448
449    #[test]
450    fn big() {
451        let tuple = (
452            false,
453            0i8,
454            0i16,
455            0i32,
456            0i64,
457            0i128,
458            I256::ZERO,
459            // 0u8,
460            0u16,
461            0u32,
462            0u64,
463            0u128,
464            U256::ZERO,
465            Address::ZERO,
466            Function::ZERO,
467        );
468        let encoded = tuple.abi_encode();
469        assert_eq!(encoded.len(), 32 * 14);
470        assert!(encoded.iter().all(|&b| b == 0));
471    }
472
473    #[test]
474    fn complex() {
475        let tuple = ((((((false,),),),),),);
476        assert_eq!(tuple.abi_encode(), Word::ZERO[..]);
477        assert_eq!(tuple.sol_name(), "((((((bool))))))");
478
479        let tuple = (
480            42u64,
481            "hello world",
482            true,
483            (
484                String::from("aaaa"),
485                Address::with_last_byte(69),
486                b"bbbb".to_vec(),
487                b"cccc",
488                &b"dddd"[..],
489            ),
490        );
491        assert_eq!(tuple.sol_name(), "(uint64,string,bool,(string,address,bytes,bytes4,bytes))");
492    }
493
494    #[test]
495    fn derefs() {
496        let x: &[Address; 0] = &[];
497        x.abi_encode();
498        assert_eq!(x.sol_name(), "address[0]");
499
500        let x = &[Address::ZERO];
501        x.abi_encode();
502        assert_eq!(x.sol_name(), "address[1]");
503
504        let x = &[Address::ZERO, Address::ZERO];
505        x.abi_encode();
506        assert_eq!(x.sol_name(), "address[2]");
507
508        let x = &[Address::ZERO][..];
509        x.abi_encode();
510        assert_eq!(x.sol_name(), "address[]");
511
512        let mut x = *b"0";
513        let x = (&mut x, *b"aaaa", b"00");
514        x.abi_encode();
515        assert_eq!(x.sol_name(), "(bytes1,bytes4,bytes2)");
516
517        let tuple = &(&0u16, &"", b"0", &mut [Address::ZERO][..]);
518        tuple.abi_encode();
519        assert_eq!(tuple.sol_name(), "(uint16,string,bytes1,address[])");
520    }
521
522    #[test]
523    fn decode() {
524        let _: Result<String> = String::abi_decode(b"");
525
526        let _: Result<Vec<String>> = Vec::<String>::abi_decode(b"");
527
528        let _: Result<(u64, String, U256)> = <(u64, String, U256)>::abi_decode(b"");
529        let _: Result<(i64, Vec<(u32, String, Vec<FixedBytes<4>>)>, U256)> =
530            <(i64, Vec<(u32, String, Vec<FixedBytes<4>>)>, U256)>::abi_decode(b"");
531    }
532
533    #[test]
534    fn empty_spec() {
535        assert_eq!("".abi_encode(), crate::abi::EMPTY_BYTES);
536        assert_eq!(b"".abi_encode(), crate::abi::EMPTY_BYTES);
537        assert_eq!(
538            ("", "a").abi_encode(),
539            <(sol_data::String, sol_data::String)>::abi_encode(&("", "a"))
540        );
541        assert_eq!(
542            ("a", "").abi_encode(),
543            <(sol_data::String, sol_data::String)>::abi_encode(&("a", ""))
544        );
545        assert_eq!(
546            (&b""[..], &b"a"[..]).abi_encode(),
547            <(sol_data::Bytes, sol_data::Bytes)>::abi_encode(&(b"", b"a"))
548        );
549        assert_eq!(
550            (&b"a"[..], &b""[..]).abi_encode(),
551            <(sol_data::Bytes, sol_data::Bytes)>::abi_encode(&(b"a", b""))
552        );
553    }
554}