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
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 #[inline]
51 fn tokenize(&self) -> <Self::SolType as SolType>::Token<'_> {
52 <Self as SolTypeValue<Self::SolType>>::stv_to_tokens(self)
53 }
54
55 #[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 #[inline]
70 fn abi_encoded_size(&self) -> usize {
71 <Self as SolTypeValue<Self::SolType>>::stv_abi_encoded_size(self)
72 }
73
74 #[inline]
79 fn eip712_data_word(&self) -> Word {
80 <Self as SolTypeValue<Self::SolType>>::stv_eip712_data_word(self)
81 }
82
83 #[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 #[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 #[inline]
105 fn abi_encode(&self) -> Vec<u8> {
106 Self::SolType::abi_encode(self)
107 }
108
109 #[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 #[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 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 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 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 #[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 #[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 #[inline]
187 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 #[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 #[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 #[inline]
226 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 [] 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 [] 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 [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
347impl 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 #[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 assert_eq!(b"".abi_encode(), encode_bytes(b""));
471 assert_eq!((b"" as &[_]).abi_encode(), encode_bytes(b""));
472 assert_eq!(b"a".abi_encode()[0], b'a');
474 assert_eq!(b"a".abi_encode()[1..], Word::ZERO[1..]);
475 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 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}