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 /// Tokenize the call's return values.
48 fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_>;
49
50 /// The size of the encoded data in bytes, **without** its selector.
51 #[inline]
52 fn abi_encoded_size(&self) -> usize {
53 if let Some(size) = <Self::Parameters<'_> as SolType>::ENCODED_SIZE {
54 return size;
55 }
56
57 // `total_words` includes the first dynamic offset which we ignore.
58 let offset = <<Self::Parameters<'_> as SolType>::Token<'_> as Token>::DYNAMIC as usize * 32;
59 (self.tokenize().total_words() * Word::len_bytes()).saturating_sub(offset)
60 }
61
62 /// ABI decode this call's arguments from the given slice, **without** its
63 /// selector.
64 #[inline]
65 fn abi_decode_raw(data: &[u8]) -> Result<Self> {
66 <Self::Parameters<'_> as SolType>::abi_decode_sequence(data).map(Self::new)
67 }
68
69 /// ABI decode this call's arguments from the given slice, **without** its
70 /// selector, with validation.
71 ///
72 /// This is the same as [`abi_decode_raw`](Self::abi_decode_raw), but performs
73 /// validation checks on the decoded parameters tuple.
74 #[inline]
75 fn abi_decode_raw_validate(data: &[u8]) -> Result<Self> {
76 <Self::Parameters<'_> as SolType>::abi_decode_sequence_validate(data).map(Self::new)
77 }
78
79 /// ABI decode this call's arguments from the given slice, **with** the
80 /// selector.
81 #[inline]
82 fn abi_decode(data: &[u8]) -> Result<Self> {
83 let data = data
84 .strip_prefix(&Self::SELECTOR)
85 .ok_or_else(|| crate::Error::type_check_fail_sig(data, Self::SIGNATURE))?;
86 Self::abi_decode_raw(data)
87 }
88
89 /// ABI decode this call's arguments from the given slice, **with** the
90 /// selector, with validation.
91 ///
92 /// This is the same as [`abi_decode`](Self::abi_decode), but performs
93 /// validation checks on the decoded parameters tuple.
94 #[inline]
95 fn abi_decode_validate(data: &[u8]) -> Result<Self> {
96 let data = data
97 .strip_prefix(&Self::SELECTOR)
98 .ok_or_else(|| crate::Error::type_check_fail_sig(data, Self::SIGNATURE))?;
99 Self::abi_decode_raw_validate(data)
100 }
101
102 /// ABI encode the call to the given buffer **without** its selector.
103 #[inline]
104 fn abi_encode_raw(&self, out: &mut Vec<u8>) {
105 out.reserve(self.abi_encoded_size());
106 out.extend(crate::abi::encode_sequence(&self.tokenize()));
107 }
108
109 /// ABI encode the call to the given buffer **with** its selector.
110 #[inline]
111 fn abi_encode(&self) -> Vec<u8> {
112 let mut out = Vec::with_capacity(4 + self.abi_encoded_size());
113 out.extend(&Self::SELECTOR);
114 self.abi_encode_raw(&mut out);
115 out
116 }
117
118 /// ABI decode this call's return values from the given slice.
119 fn abi_decode_returns(data: &[u8]) -> Result<Self::Return>;
120
121 /// ABI decode this call's return values from the given slice, with validation.
122 ///
123 /// This is the same as [`abi_decode_returns`](Self::abi_decode_returns), but performs
124 /// validation checks on the decoded return tuple.
125 fn abi_decode_returns_validate(data: &[u8]) -> Result<Self::Return>;
126
127 /// ABI encode the call's return value.
128 #[inline]
129 fn abi_encode_returns(ret: &Self::Return) -> Vec<u8> {
130 crate::abi::encode_sequence(&Self::tokenize_returns(ret))
131 }
132
133 /// ABI encode the call's return values.
134 #[inline]
135 fn abi_encode_returns_tuple<'a, E>(e: &'a E) -> Vec<u8>
136 where
137 E: SolTypeValue<Self::ReturnTuple<'a>>,
138 {
139 crate::abi::encode_sequence(&e.stv_to_tokens())
140 }
141}
142
143/// A Solidity constructor.
144pub trait SolConstructor: Sized {
145 /// The underlying tuple type which represents this type's arguments.
146 ///
147 /// If this type has no arguments, this will be the unit type `()`.
148 type Parameters<'a>: SolType<Token<'a> = Self::Token<'a>>;
149
150 /// The arguments' corresponding [TokenSeq] type.
151 type Token<'a>: TokenSeq<'a>;
152
153 /// Convert from the tuple type used for ABI encoding and decoding.
154 fn new(tuple: <Self::Parameters<'_> as SolType>::RustType) -> Self;
155
156 /// Tokenize the call's arguments.
157 fn tokenize(&self) -> Self::Token<'_>;
158
159 /// The size of the encoded data in bytes.
160 #[inline]
161 fn abi_encoded_size(&self) -> usize {
162 if let Some(size) = <Self::Parameters<'_> as SolType>::ENCODED_SIZE {
163 return size;
164 }
165
166 // `total_words` includes the first dynamic offset which we ignore.
167 let offset = <<Self::Parameters<'_> as SolType>::Token<'_> as Token>::DYNAMIC as usize * 32;
168 (self.tokenize().total_words() * Word::len_bytes()).saturating_sub(offset)
169 }
170
171 /// ABI encode the call to the given buffer.
172 #[inline]
173 fn abi_encode(&self) -> Vec<u8> {
174 crate::abi::encode_sequence(&self.tokenize())
175 }
176}