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
11pub trait SolValue: SolTypeValue<Self::SolType> {
36 type SolType: SolType;
38
39 #[inline]
43 fn sol_name(&self) -> &'static str {
44 Self::SolType::SOL_NAME
45 }
46
47 #[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 #[inline]
60 fn tokenize(&self) -> <Self::SolType as SolType>::Token<'_> {
61 <Self as SolTypeValue<Self::SolType>>::stv_to_tokens(self)
62 }
63
64 #[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 #[inline]
79 fn abi_encoded_size(&self) -> usize {
80 <Self as SolTypeValue<Self::SolType>>::stv_abi_encoded_size(self)
81 }
82
83 #[inline]
88 fn eip712_data_word(&self) -> Word {
89 <Self as SolTypeValue<Self::SolType>>::stv_eip712_data_word(self)
90 }
91
92 #[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 #[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 #[inline]
114 fn abi_encode(&self) -> Vec<u8> {
115 Self::SolType::abi_encode(self)
116 }
117
118 #[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 #[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 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 #[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 #[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 [] 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 [] 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 [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
285impl 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 #[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 assert_eq!(b"".abi_encode(), encode_bytes(b""));
409 assert_eq!((b"" as &[_]).abi_encode(), encode_bytes(b""));
410 assert_eq!(b"a".abi_encode()[0], b'a');
412 assert_eq!(b"a".abi_encode()[1..], Word::ZERO[1..]);
413 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 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}