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