1#[macro_use]
18mod macros;
19
20mod bytes;
21mod encodable;
22mod error;
23mod params;
24mod result;
25mod types;
26
27#[cfg(test)]
28mod tests;
29
30use core::ops::Deref;
31
32use alloy_sol_types::{
33 sol_data,
34 SolType as AlloySolType,
35};
36use impl_trait_for_tuples::impl_for_tuples;
37use ink_prelude::{
38 borrow::Cow,
39 boxed::Box,
40 string::String,
41 vec::Vec,
42};
43use itertools::Itertools;
44use primitive_types::{
45 H256,
46 U256,
47};
48use sp_weights::Weight;
49
50pub use self::{
51 bytes::{
52 DynBytes,
53 FixedBytes,
54 },
55 error::{
56 SolErrorDecode,
57 SolErrorEncode,
58 },
59 params::{
60 SolParamsDecode,
61 SolParamsEncode,
62 },
63 result::{
64 SolResultDecode,
65 SolResultDecodeError,
66 },
67 types::{
68 SolTypeDecode,
69 SolTypeEncode,
70 },
71};
72
73use crate::types::{
74 AccountId,
75 Address,
76 Hash,
77};
78
79pub trait SolDecode: Sized {
118 type SolType: SolTypeDecode;
120
121 const SOL_NAME: &'static str =
123 <<Self::SolType as SolTypeDecode>::AlloyType as AlloySolType>::SOL_NAME;
124
125 fn decode(data: &[u8]) -> Result<Self, Error> {
127 <Self::SolType as SolTypeDecode>::decode(data).and_then(Self::from_sol_type)
128 }
129
130 fn from_sol_type(value: Self::SolType) -> Result<Self, Error>;
132}
133
134pub trait SolEncode<'a> {
168 type SolType: SolTypeEncode;
174
175 const SOL_NAME: &'static str =
177 <<Self::SolType as SolTypeEncode>::AlloyType as AlloySolType>::SOL_NAME;
178
179 #[doc(hidden)]
181 const DYNAMIC: bool =
182 <<Self::SolType as SolTypeEncode>::AlloyType as AlloySolType>::DYNAMIC;
183
184 fn encode(&'a self) -> Vec<u8> {
186 <Self::SolType as SolTypeEncode>::encode(&self.to_sol_type())
187 }
188
189 fn to_sol_type(&'a self) -> Self::SolType;
192}
193
194#[derive(Debug, PartialEq)]
196pub struct Error;
197
198impl From<alloy_sol_types::Error> for Error {
199 fn from(_: alloy_sol_types::Error) -> Self {
200 Self
201 }
202}
203
204impl core::fmt::Display for Error {
205 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
206 f.write_str("Solidity ABI encode/decode error")
207 }
208}
209
210macro_rules! impl_primitive_decode {
211 ($($ty: ty),+ $(,)*) => {
212 $(
213 impl SolDecode for $ty {
214 type SolType = $ty;
215
216 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
217 Ok(value)
218 }
219 }
220 )*
221 };
222}
223
224macro_rules! impl_primitive_encode {
225 ($($ty: ty),+ $(,)*) => {
226 $(
227 impl SolEncode<'_> for $ty {
228 type SolType = $ty;
229
230 fn to_sol_type(&self) -> Self::SolType {
231 *self
232 }
233 }
234 )*
235 };
236}
237
238macro_rules! impl_primitive {
239 ($($ty: ty),+ $(,)*) => {
240 $(
241 impl_primitive_decode!($ty);
242
243 impl_primitive_encode!($ty);
244 )*
245 };
246}
247
248macro_rules! impl_primitive_encode_by_ref {
249 ($($ty: ty, $ref_ty: ty),+ $(,)*) => {
250 $(
251 impl<'a> SolEncode<'a> for $ty {
252 type SolType = &'a $ref_ty;
253
254 fn to_sol_type(&'a self) -> Self::SolType {
255 self
256 }
257 }
258 )*
259 };
260}
261
262macro_rules! impl_primitive_by_ref {
263 ($($ty: ty, $ref_ty: ty),+ $(,)*) => {
264 $(
265 impl_primitive_decode!($ty);
266
267 impl_primitive_encode_by_ref!($ty, $ref_ty);
268 )*
269 };
270}
271
272impl_primitive! {
273 bool,
275 i8, i16, i32, i64, i128,
277 u8, u16, u32, u64, u128, U256,
279 Address,
281}
282
283impl_primitive_by_ref! {
284 String, str,
286 Box<str>, str,
287}
288
289impl<T: SolDecode, const N: usize> SolDecode for [T; N] {
291 type SolType = [T::SolType; N];
292
293 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
294 value
298 .into_iter()
299 .map(<T as SolDecode>::from_sol_type)
300 .process_results(|iter| iter.collect_array())?
301 .ok_or(Error)
302 }
303}
304
305impl<'a, T: SolEncode<'a>, const N: usize> SolEncode<'a> for [T; N] {
306 type SolType = [T::SolType; N];
307
308 fn to_sol_type(&'a self) -> Self::SolType {
309 self.each_ref().map(<T as SolEncode>::to_sol_type)
310 }
311}
312
313impl<T: SolDecode> SolDecode for Vec<T> {
315 type SolType = Vec<T::SolType>;
316
317 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
318 value
319 .into_iter()
320 .map(<T as SolDecode>::from_sol_type)
321 .collect()
322 }
323}
324
325impl<'a, T: SolEncode<'a>> SolEncode<'a> for Vec<T> {
326 type SolType = Vec<T::SolType>;
327
328 fn to_sol_type(&'a self) -> Self::SolType {
329 self.iter().map(<T as SolEncode>::to_sol_type).collect()
330 }
331}
332
333impl<T: SolDecode> SolDecode for Box<[T]> {
335 type SolType = Box<[T::SolType]>;
336
337 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
338 core::iter::IntoIterator::into_iter(value)
342 .map(<T as SolDecode>::from_sol_type)
343 .process_results(|iter| iter.collect())
344 }
345}
346
347impl<'a, T: SolEncode<'a>> SolEncode<'a> for Box<[T]> {
348 type SolType = Box<[T::SolType]>;
349
350 fn to_sol_type(&'a self) -> Self::SolType {
351 self.iter().map(<T as SolEncode>::to_sol_type).collect()
352 }
353}
354
355#[impl_for_tuples(12)]
359impl SolDecode for Tuple {
360 for_tuples!( type SolType = ( #( Tuple::SolType ),* ); );
361
362 #[allow(clippy::unused_unit)]
363 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
364 Ok(for_tuples! { ( #( Tuple::from_sol_type(value.Tuple)? ),* ) })
365 }
366}
367
368#[impl_for_tuples(12)]
369impl<'a> SolEncode<'a> for Tuple {
370 for_tuples!( type SolType = ( #( Tuple::SolType ),* ); );
371
372 #[allow(clippy::unused_unit)]
373 fn to_sol_type(&'a self) -> Self::SolType {
374 for_tuples!( ( #( self.Tuple.to_sol_type() ),* ) )
375 }
376}
377
378macro_rules! impl_refs_encode {
380 ($($ty: ty), +$(,)*) => {
381 $(
382 impl<'a, T> SolEncode<'a> for $ty
383 where
384 T: SolEncode<'a>,
385 {
386 type SolType = T::SolType;
387
388 fn to_sol_type(&'a self) -> Self::SolType {
389 <T as SolEncode>::to_sol_type(self)
390 }
391 }
392 )*
393 };
394}
395
396impl_refs_encode! {
397 &T,
398 &mut T,
399 Box<T>,
400}
401
402impl<'a, T> SolEncode<'a> for Cow<'_, T>
403where
404 T: SolEncode<'a> + Clone,
405{
406 type SolType = T::SolType;
407
408 fn to_sol_type(&'a self) -> Self::SolType {
409 <T as SolEncode>::to_sol_type(self.deref())
410 }
411}
412
413macro_rules! impl_str_ref_encode {
415 ($($ty: ty),+ $(,)*) => {
416 $(
417 impl<'a> SolEncode<'a> for $ty {
418 type SolType = &'a str;
419
420 fn to_sol_type(&'a self) -> Self::SolType {
421 self
422 }
423 }
424 )*
425 };
426}
427
428impl_str_ref_encode!(&str, &mut str);
429
430macro_rules! impl_slice_ref_encode {
431 ($($ty: ty),+ $(,)*) => {
432 $(
433 impl<'a, T> SolEncode<'a> for $ty
434 where
435 T: SolEncode<'a>,
436 {
437 type SolType = Vec<T::SolType>;
438
439 fn to_sol_type(&'a self) -> Self::SolType {
440 self.iter().map(<T as SolEncode>::to_sol_type).collect()
441 }
442 }
443 )*
444 };
445}
446
447impl_slice_ref_encode!(&[T], &mut [T]);
448
449impl<T> SolDecode for Option<T>
470where
471 T: SolDecode,
472{
473 type SolType = Option<T::SolType>;
474
475 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
476 value.map(<T as SolDecode>::from_sol_type).transpose()
477 }
478}
479
480impl<'a, T> SolEncode<'a> for Option<T>
481where
482 T: SolEncode<'a>,
483{
484 type SolType = Option<T::SolType>;
485
486 fn to_sol_type(&'a self) -> Self::SolType {
487 self.as_ref().map(T::to_sol_type)
488 }
489}
490
491impl<T> SolDecode for core::marker::PhantomData<T> {
493 type SolType = ();
494
495 fn decode(data: &[u8]) -> Result<Self, Error>
496 where
497 Self: Sized,
498 {
499 if data.is_empty() {
500 Ok(core::marker::PhantomData)
501 } else {
502 Err(Error)
503 }
504 }
505
506 fn from_sol_type(_: Self::SolType) -> Result<Self, Error> {
507 Ok(core::marker::PhantomData)
508 }
509}
510
511impl<T> SolEncode<'_> for core::marker::PhantomData<T> {
512 type SolType = ();
513
514 fn encode(&self) -> Vec<u8> {
515 Vec::new()
516 }
517
518 fn to_sol_type(&self) {}
519}
520
521impl SolDecode for AccountId {
523 type SolType = FixedBytes<32>;
524
525 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
526 Ok(AccountId(value.0))
527 }
528}
529
530impl SolEncode<'_> for AccountId {
531 type SolType = FixedBytes<32>;
532
533 fn encode(&self) -> Vec<u8> {
534 sol_data::FixedBytes::abi_encode(self)
536 }
537
538 fn to_sol_type(&self) -> Self::SolType {
539 FixedBytes(self.0)
545 }
546}
547
548impl SolDecode for Hash {
550 type SolType = FixedBytes<32>;
551
552 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
553 Ok(Hash::from(value.0))
554 }
555}
556
557impl SolEncode<'_> for Hash {
558 type SolType = FixedBytes<32>;
559
560 fn encode(&self) -> Vec<u8> {
561 sol_data::FixedBytes::abi_encode(self)
563 }
564
565 fn to_sol_type(&self) -> Self::SolType {
566 FixedBytes((*self).into())
572 }
573}
574
575impl SolDecode for H256 {
577 type SolType = FixedBytes<32>;
578
579 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
580 Ok(H256(value.0))
581 }
582}
583
584impl SolEncode<'_> for H256 {
585 type SolType = FixedBytes<32>;
586
587 fn encode(&self) -> Vec<u8> {
588 sol_data::FixedBytes::abi_encode(&self.0)
590 }
591
592 fn to_sol_type(&self) -> Self::SolType {
593 FixedBytes(self.0)
599 }
600}
601
602impl SolDecode for Weight {
604 type SolType = (u64, u64);
605
606 fn from_sol_type(value: Self::SolType) -> Result<Self, Error> {
607 Ok(Weight::from_parts(value.0, value.1))
608 }
609}
610
611impl SolEncode<'_> for Weight {
612 type SolType = (u64, u64);
613
614 fn to_sol_type(&self) -> Self::SolType {
615 (self.ref_time(), self.proof_size())
616 }
617}