alloy_sol_types/types/
value.rs

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