@@ -30,6 +30,8 @@ pub trait FunctionExt {
3030 fn abi_decode_output ( & self , data : & [ u8 ] ) -> Result < Vec < DynSolValue > > ;
3131
3232 /// ABI-encodes the given values, prefixed by the function's selector, if any.
33+ ///
34+ /// This behaviour is to ensure consistency with `ethabi`.
3335 fn abi_encode_input ( & self , values : & [ DynSolValue ] ) -> Result < Vec < u8 > > ;
3436}
3537
@@ -160,3 +162,142 @@ fn fix_type_size<'a>(ty: &DynSolType, val: &'a DynSolValue) -> Result<Cow<'a, Dy
160162
161163 Ok ( Cow :: Owned ( new_val) )
162164}
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