ink_primitives/sol/
params.rs

1// Copyright (C) ink! contributors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use alloy_sol_types::{
16    abi::{
17        self,
18        Encoder,
19    },
20    SolType as AlloySolType,
21};
22use impl_trait_for_tuples::impl_for_tuples;
23use ink_prelude::vec::Vec;
24
25use super::{
26    encodable::{
27        Encodable,
28        EncodableParams,
29    },
30    Error,
31    SolDecode,
32    SolEncode,
33    SolTypeDecode,
34    SolTypeEncode,
35};
36
37/// Solidity ABI decode function parameters.
38///
39/// # Note
40///
41/// This trait is sealed and cannot be implemented for types outside `ink_primitives`.
42pub trait SolParamsDecode: SolDecode + Sized + private::Sealed {
43    /// Name of equivalent Solidity ABI type.
44    const SOL_NAME: &'static str = <Self as SolDecode>::SOL_NAME;
45
46    /// Solidity ABI decode function parameters into this type.
47    fn decode(data: &[u8]) -> Result<Self, Error>;
48}
49
50/// Solidity ABI encode function parameters.
51///
52/// # Note
53///
54/// This trait is sealed and cannot be implemented for types outside `ink_primitives`.
55pub trait SolParamsEncode<'a>: SolEncode<'a> + private::Sealed {
56    /// Name of equivalent Solidity ABI type.
57    const SOL_NAME: &'static str = <Self as SolEncode<'a>>::SOL_NAME;
58
59    /// Solidity ABI encode the value as function parameters.
60    fn encode(&'a self) -> Vec<u8>;
61}
62
63// We follow the Rust standard library's convention of implementing traits for tuples up
64// to twelve items long.
65// Ref: <https://doc.rust-lang.org/std/primitive.tuple.html#trait-implementations>
66#[impl_for_tuples(12)]
67#[tuple_types_custom_trait_bound(SolDecode)]
68impl SolParamsDecode for Tuple {
69    fn decode(data: &[u8]) -> Result<Self, Error> {
70        abi::decode_params::<
71            <<<Self as SolDecode>::SolType as SolTypeDecode>::AlloyType as AlloySolType>::Token<'_>,
72        >(data)
73            .map_err(Error::from)
74            .and_then(<<Self as SolDecode>::SolType as SolTypeDecode>::detokenize)
75            .and_then(<Self as SolDecode>::from_sol_type)
76    }
77}
78
79#[impl_for_tuples(1, 12)]
80#[tuple_types_custom_trait_bound(SolEncode<'a>)]
81impl<'a> SolParamsEncode<'a> for Tuple {
82    fn encode(&'a self) -> Vec<u8> {
83        let params = self.to_sol_type();
84        let token = <<Self as SolEncode>::SolType as SolTypeEncode>::tokenize(&params);
85        let mut encoder = Encoder::with_capacity(token.total_words());
86        EncodableParams::encode_params(&token, &mut encoder);
87        encoder.into_bytes()
88    }
89}
90
91// Optimized implementation for unit (i.e. `()`).
92impl SolParamsEncode<'_> for () {
93    fn encode(&self) -> Vec<u8> {
94        Vec::new()
95    }
96}
97
98#[impl_for_tuples(12)]
99#[tuple_types_no_default_trait_bound]
100impl private::Sealed for Tuple {}
101
102mod private {
103    /// Seals implementations of `SolParamsEncode` and `SolParamsDecode`.
104    pub trait Sealed {}
105}