alloy_sol_types/types/
function.rs

1use crate::{
2    abi::{Token, TokenSeq},
3    private::SolTypeValue,
4    Result, SolType, Word,
5};
6use alloc::vec::Vec;
7
8/// A Solidity function call.
9///
10/// # Implementer's Guide
11///
12/// It should not be necessary to implement this trait manually. Instead, use
13/// the [`sol!`](crate::sol!) procedural macro to parse Solidity syntax into
14/// types that implement this trait.
15pub trait SolCall: Sized {
16    /// The underlying tuple type which represents this type's arguments.
17    ///
18    /// If this type has no arguments, this will be the unit type `()`.
19    type Parameters<'a>: SolType<Token<'a> = Self::Token<'a>>;
20
21    /// The arguments' corresponding [TokenSeq] type.
22    type Token<'a>: TokenSeq<'a>;
23
24    /// The function's return struct.
25    type Return;
26
27    /// The underlying tuple type which represents this type's return values.
28    ///
29    /// If this type has no return values, this will be the unit type `()`.
30    type ReturnTuple<'a>: SolType<Token<'a> = Self::ReturnToken<'a>>;
31
32    /// The returns' corresponding [TokenSeq] type.
33    type ReturnToken<'a>: TokenSeq<'a>;
34
35    /// The function's ABI signature.
36    const SIGNATURE: &'static str;
37
38    /// The function selector: `keccak256(SIGNATURE)[0..4]`
39    const SELECTOR: [u8; 4];
40
41    /// Convert from the tuple type used for ABI encoding and decoding.
42    fn new(tuple: <Self::Parameters<'_> as SolType>::RustType) -> Self;
43
44    /// Tokenize the call's arguments.
45    fn tokenize(&self) -> Self::Token<'_>;
46
47    /// The size of the encoded data in bytes, **without** its selector.
48    #[inline]
49    fn abi_encoded_size(&self) -> usize {
50        if let Some(size) = <Self::Parameters<'_> as SolType>::ENCODED_SIZE {
51            return size;
52        }
53
54        // `total_words` includes the first dynamic offset which we ignore.
55        let offset = <<Self::Parameters<'_> as SolType>::Token<'_> as Token>::DYNAMIC as usize * 32;
56        (self.tokenize().total_words() * Word::len_bytes()).saturating_sub(offset)
57    }
58
59    /// ABI decode this call's arguments from the given slice, **without** its
60    /// selector.
61    #[inline]
62    fn abi_decode_raw(data: &[u8], validate: bool) -> Result<Self> {
63        <Self::Parameters<'_> as SolType>::abi_decode_sequence(data, validate).map(Self::new)
64    }
65
66    /// ABI decode this call's arguments from the given slice, **with** the
67    /// selector.
68    #[inline]
69    fn abi_decode(data: &[u8], validate: bool) -> Result<Self> {
70        let data = data
71            .strip_prefix(&Self::SELECTOR)
72            .ok_or_else(|| crate::Error::type_check_fail_sig(data, Self::SIGNATURE))?;
73        Self::abi_decode_raw(data, validate)
74    }
75
76    /// ABI encode the call to the given buffer **without** its selector.
77    #[inline]
78    fn abi_encode_raw(&self, out: &mut Vec<u8>) {
79        out.reserve(self.abi_encoded_size());
80        out.extend(crate::abi::encode_sequence(&self.tokenize()));
81    }
82
83    /// ABI encode the call to the given buffer **with** its selector.
84    #[inline]
85    fn abi_encode(&self) -> Vec<u8> {
86        let mut out = Vec::with_capacity(4 + self.abi_encoded_size());
87        out.extend(&Self::SELECTOR);
88        self.abi_encode_raw(&mut out);
89        out
90    }
91
92    /// ABI decode this call's return values from the given slice.
93    fn abi_decode_returns(data: &[u8], validate: bool) -> Result<Self::Return>;
94
95    /// ABI encode the call's return values.
96    #[inline]
97    fn abi_encode_returns<'a, E>(e: &'a E) -> Vec<u8>
98    where
99        E: SolTypeValue<Self::ReturnTuple<'a>>,
100    {
101        crate::abi::encode_sequence(&e.stv_to_tokens())
102    }
103}
104
105/// A Solidity constructor.
106pub trait SolConstructor: Sized {
107    /// The underlying tuple type which represents this type's arguments.
108    ///
109    /// If this type has no arguments, this will be the unit type `()`.
110    type Parameters<'a>: SolType<Token<'a> = Self::Token<'a>>;
111
112    /// The arguments' corresponding [TokenSeq] type.
113    type Token<'a>: TokenSeq<'a>;
114
115    /// Convert from the tuple type used for ABI encoding and decoding.
116    fn new(tuple: <Self::Parameters<'_> as SolType>::RustType) -> Self;
117
118    /// Tokenize the call's arguments.
119    fn tokenize(&self) -> Self::Token<'_>;
120
121    /// The size of the encoded data in bytes.
122    #[inline]
123    fn abi_encoded_size(&self) -> usize {
124        if let Some(size) = <Self::Parameters<'_> as SolType>::ENCODED_SIZE {
125            return size;
126        }
127
128        // `total_words` includes the first dynamic offset which we ignore.
129        let offset = <<Self::Parameters<'_> as SolType>::Token<'_> as Token>::DYNAMIC as usize * 32;
130        (self.tokenize().total_words() * Word::len_bytes()).saturating_sub(offset)
131    }
132
133    /// ABI encode the call to the given buffer.
134    #[inline]
135    fn abi_encode(&self) -> Vec<u8> {
136        crate::abi::encode_sequence(&self.tokenize())
137    }
138}