@@ -30,6 +30,8 @@ pub trait FunctionExt {
30
30
fn abi_decode_output ( & self , data : & [ u8 ] ) -> Result < Vec < DynSolValue > > ;
31
31
32
32
/// ABI-encodes the given values, prefixed by the function's selector, if any.
33
+ ///
34
+ /// This behaviour is to ensure consistency with `ethabi`.
33
35
fn abi_encode_input ( & self , values : & [ DynSolValue ] ) -> Result < Vec < u8 > > ;
34
36
}
35
37
@@ -160,3 +162,142 @@ fn fix_type_size<'a>(ty: &DynSolType, val: &'a DynSolValue) -> Result<Cow<'a, Dy
160
162
161
163
Ok ( Cow :: Owned ( new_val) )
162
164
}
165
+
166
+ #[ cfg( test) ]
167
+ mod tests {
168
+ use alloy:: primitives:: I256 ;
169
+ use alloy:: primitives:: U256 ;
170
+
171
+ use super :: * ;
172
+
173
+ fn s ( f : & str ) -> String {
174
+ Function :: parse ( f) . unwrap ( ) . signature_compat ( )
175
+ }
176
+
177
+ fn u256 ( u : u64 ) -> U256 {
178
+ U256 :: from ( u)
179
+ }
180
+
181
+ fn i256 ( i : i32 ) -> I256 {
182
+ I256 :: try_from ( i) . unwrap ( )
183
+ }
184
+
185
+ #[ test]
186
+ fn signature_compat_no_inputs_no_outputs ( ) {
187
+ assert_eq ! ( s( "x()" ) , "x()" ) ;
188
+ }
189
+
190
+ #[ test]
191
+ fn signature_compat_one_input_no_outputs ( ) {
192
+ assert_eq ! ( s( "x(uint256 a)" ) , "x(uint256)" ) ;
193
+ }
194
+
195
+ #[ test]
196
+ fn signature_compat_multiple_inputs_no_outputs ( ) {
197
+ assert_eq ! ( s( "x(uint256 a, bytes32 b)" ) , "x(uint256,bytes32)" ) ;
198
+ }
199
+
200
+ #[ test]
201
+ fn signature_compat_no_inputs_one_output ( ) {
202
+ assert_eq ! ( s( "x() returns (uint256)" ) , "x():(uint256)" ) ;
203
+ }
204
+
205
+ #[ test]
206
+ fn signature_compat_no_inputs_multiple_outputs ( ) {
207
+ assert_eq ! ( s( "x() returns (uint256, bytes32)" ) , "x():(uint256,bytes32)" ) ;
208
+ }
209
+
210
+ #[ test]
211
+ fn signature_compat_multiple_inputs_multiple_outputs ( ) {
212
+ assert_eq ! (
213
+ s( "x(bytes32 a, uint256 b) returns (uint256, bytes32)" ) ,
214
+ "x(bytes32,uint256):(uint256,bytes32)" ,
215
+ ) ;
216
+ }
217
+
218
+ #[ test]
219
+ fn abi_decode_input ( ) {
220
+ use DynSolValue :: { Int , Tuple , Uint } ;
221
+
222
+ let f = Function :: parse ( "x(uint256 a, int256 b)" ) . unwrap ( ) ;
223
+ let data = Tuple ( vec ! [ Uint ( u256( 10 ) , 256 ) , Int ( i256( -10 ) , 256 ) ] ) . abi_encode_params ( ) ;
224
+ let inputs = f. abi_decode_input ( & data) . unwrap ( ) ;
225
+
226
+ assert_eq ! ( inputs, vec![ Uint ( u256( 10 ) , 256 ) , Int ( i256( -10 ) , 256 ) ] ) ;
227
+ }
228
+
229
+ #[ test]
230
+ fn abi_decode_output ( ) {
231
+ use DynSolValue :: { Int , Tuple , Uint } ;
232
+
233
+ let f = Function :: parse ( "x() returns (uint256 a, int256 b)" ) . unwrap ( ) ;
234
+ let data = Tuple ( vec ! [ Uint ( u256( 10 ) , 256 ) , Int ( i256( -10 ) , 256 ) ] ) . abi_encode_params ( ) ;
235
+ let outputs = f. abi_decode_output ( & data) . unwrap ( ) ;
236
+
237
+ assert_eq ! ( outputs, vec![ Uint ( u256( 10 ) , 256 ) , Int ( i256( -10 ) , 256 ) ] ) ;
238
+ }
239
+
240
+ #[ test]
241
+ fn abi_encode_input_no_values ( ) {
242
+ let f = Function :: parse ( "x(uint256 a, int256 b)" ) . unwrap ( ) ;
243
+ let err = f. abi_encode_input ( & [ ] ) . unwrap_err ( ) ;
244
+
245
+ assert_eq ! (
246
+ err. to_string( ) ,
247
+ "unexpected number of values; expected 2, got 0" ,
248
+ ) ;
249
+ }
250
+
251
+ #[ test]
252
+ fn abi_encode_input_too_many_values ( ) {
253
+ use DynSolValue :: Bool ;
254
+
255
+ let f = Function :: parse ( "x(uint256 a, int256 b)" ) . unwrap ( ) ;
256
+
257
+ let err = f
258
+ . abi_encode_input ( & [ Bool ( true ) , Bool ( false ) , Bool ( true ) ] )
259
+ . unwrap_err ( ) ;
260
+
261
+ assert_eq ! (
262
+ err. to_string( ) ,
263
+ "unexpected number of values; expected 2, got 3" ,
264
+ ) ;
265
+ }
266
+
267
+ #[ test]
268
+ fn abi_encode_input_invalid_types ( ) {
269
+ use DynSolValue :: Bool ;
270
+
271
+ let f = Function :: parse ( "x(uint256 a, int256 b)" ) . unwrap ( ) ;
272
+ let err = f. abi_encode_input ( & [ Bool ( true ) , Bool ( false ) ] ) . unwrap_err ( ) ;
273
+ assert ! ( err. to_string( ) . starts_with( "invalid value type;" ) ) ;
274
+ }
275
+
276
+ #[ test]
277
+ fn abi_encode_success ( ) {
278
+ use DynSolValue :: { Bool , Uint } ;
279
+
280
+ let f = Function :: parse ( "x(uint256 a, bool b)" ) . unwrap ( ) ;
281
+ let a = Uint ( u256 ( 10 ) , 256 ) ;
282
+ let b = Bool ( true ) ;
283
+
284
+ let data = f. abi_encode_input ( & [ a. clone ( ) , b. clone ( ) ] ) . unwrap ( ) ;
285
+ let inputs = f. abi_decode_input ( & data[ 4 ..] ) . unwrap ( ) ;
286
+
287
+ assert_eq ! ( inputs, vec![ a, b] ) ;
288
+ }
289
+
290
+ #[ test]
291
+ fn abi_encode_success_with_size_fix ( ) {
292
+ use DynSolValue :: { Int , Uint } ;
293
+
294
+ let f = Function :: parse ( "x(uint256 a, int256 b)" ) . unwrap ( ) ;
295
+ let a = Uint ( u256 ( 10 ) , 32 ) ;
296
+ let b = Int ( i256 ( -10 ) , 32 ) ;
297
+
298
+ let data = f. abi_encode_input ( & [ a, b] ) . unwrap ( ) ;
299
+ let inputs = f. abi_decode_input ( & data[ 4 ..] ) . unwrap ( ) ;
300
+
301
+ assert_eq ! ( inputs, vec![ Uint ( u256( 10 ) , 256 ) , Int ( i256( -10 ) , 256 ) ] ) ;
302
+ }
303
+ }
0 commit comments