@@ -29,7 +29,7 @@ enum Encode {
29
29
/// Load function from JSON ABI file.
30
30
Function {
31
31
abi_path : String ,
32
- function_name : String ,
32
+ function_name_or_signature : String ,
33
33
#[ structopt( short, number_of_values = 1 ) ]
34
34
params : Vec < String > ,
35
35
/// Allow short representation of input params.
@@ -54,7 +54,7 @@ enum Decode {
54
54
/// Load function from JSON ABI file.
55
55
Function {
56
56
abi_path : String ,
57
- function_name : String ,
57
+ function_name_or_signature : String ,
58
58
data : String ,
59
59
} ,
60
60
/// Specify types of input params inline.
@@ -87,25 +87,44 @@ where
87
87
let opt = Opt :: from_iter ( args) ;
88
88
89
89
match opt {
90
- Opt :: Encode ( Encode :: Function { abi_path, function_name , params, lenient } ) =>
91
- encode_input ( & abi_path, & function_name , & params, lenient) ,
90
+ Opt :: Encode ( Encode :: Function { abi_path, function_name_or_signature , params, lenient } ) =>
91
+ encode_input ( & abi_path, & function_name_or_signature , & params, lenient) ,
92
92
Opt :: Encode ( Encode :: Params { params, lenient } ) =>
93
93
encode_params ( & params, lenient) ,
94
- Opt :: Decode ( Decode :: Function { abi_path, function_name , data } ) =>
95
- decode_call_output ( & abi_path, & function_name , & data) ,
94
+ Opt :: Decode ( Decode :: Function { abi_path, function_name_or_signature , data } ) =>
95
+ decode_call_output ( & abi_path, & function_name_or_signature , & data) ,
96
96
Opt :: Decode ( Decode :: Params { types, data } ) =>
97
97
decode_params ( & types, & data) ,
98
98
Opt :: Decode ( Decode :: Log { abi_path, event_name_or_signature, topics, data } ) =>
99
99
decode_log ( & abi_path, & event_name_or_signature, & topics, & data) ,
100
100
}
101
101
}
102
102
103
- fn load_function ( path : & str , function : & str ) -> Result < Function , Error > {
103
+ fn load_function ( path : & str , name_or_signature : & str ) -> Result < Function , Error > {
104
104
let file = File :: open ( path) ?;
105
105
let contract = Contract :: load ( file) ?;
106
- let function = contract . function ( function ) ? . clone ( ) ;
106
+ let params_start = name_or_signature . find ( '(' ) ;
107
107
108
- Ok ( function)
108
+ match params_start {
109
+ // It's a signature
110
+ Some ( params_start) => {
111
+ let name = & name_or_signature[ ..params_start] ;
112
+
113
+ contract. functions_by_name ( name) ?. iter ( ) . find ( |f| {
114
+ f. signature ( ) == name_or_signature
115
+ } ) . cloned ( ) . ok_or ( ErrorKind :: InvalidFunctionSignature ( name_or_signature. to_owned ( ) ) . into ( ) )
116
+ } ,
117
+
118
+ // It's a name
119
+ None => {
120
+ let functions = contract. functions_by_name ( name_or_signature) ?;
121
+ match functions. len ( ) {
122
+ 0 => unreachable ! ( ) ,
123
+ 1 => Ok ( functions[ 0 ] . clone ( ) ) ,
124
+ _ => Err ( ErrorKind :: AmbiguousFunctionName ( name_or_signature. to_owned ( ) ) . into ( ) )
125
+ }
126
+ } ,
127
+ }
109
128
}
110
129
111
130
fn load_event ( path : & str , name_or_signature : & str ) -> Result < Event , Error > {
@@ -145,8 +164,8 @@ fn parse_tokens(params: &[(ParamType, &str)], lenient: bool) -> Result<Vec<Token
145
164
. map_err ( From :: from)
146
165
}
147
166
148
- fn encode_input ( path : & str , function : & str , values : & [ String ] , lenient : bool ) -> Result < String , Error > {
149
- let function = load_function ( path, function ) ?;
167
+ fn encode_input ( path : & str , name_or_signature : & str , values : & [ String ] , lenient : bool ) -> Result < String , Error > {
168
+ let function = load_function ( path, name_or_signature ) ?;
150
169
151
170
let params: Vec < _ > = function. inputs . iter ( )
152
171
. map ( |param| param. kind . clone ( ) )
@@ -174,8 +193,8 @@ fn encode_params(params: &[String], lenient: bool) -> Result<String, Error> {
174
193
Ok ( result. to_hex ( ) )
175
194
}
176
195
177
- fn decode_call_output ( path : & str , function : & str , data : & str ) -> Result < String , Error > {
178
- let function = load_function ( path, function ) ?;
196
+ fn decode_call_output ( path : & str , name_or_signature : & str , data : & str ) -> Result < String , Error > {
197
+ let function = load_function ( path, name_or_signature ) ?;
179
198
let data : Vec < u8 > = data. from_hex ( ) . chain_err ( || "Expected <data> to be hex" ) ?;
180
199
let tokens = function. decode_output ( & data) ?;
181
200
let types = function. outputs ;
@@ -271,12 +290,42 @@ mod tests {
271
290
}
272
291
273
292
#[ test]
274
- fn abi_encode ( ) {
293
+ fn function_encode_by_name ( ) {
275
294
let command = "ethabi encode function ../res/test.abi foo -p 1" . split ( " " ) ;
276
295
let expected = "455575780000000000000000000000000000000000000000000000000000000000000001" ;
277
296
assert_eq ! ( execute( command) . unwrap( ) , expected) ;
278
297
}
279
298
299
+ #[ test]
300
+ fn function_encode_by_signature ( ) {
301
+ let command = "ethabi encode function ../res/test.abi foo(bool) -p 1" . split ( " " ) ;
302
+ let expected = "455575780000000000000000000000000000000000000000000000000000000000000001" ;
303
+ assert_eq ! ( execute( command) . unwrap( ) , expected) ;
304
+ }
305
+
306
+ #[ test]
307
+ fn overloaded_function_encode_by_name ( ) {
308
+ // This should fail because there are two definitions of `bar in the ABI
309
+ let command = "ethabi encode function ../res/test.abi bar -p 1" . split ( " " ) ;
310
+ assert ! ( execute( command) . is_err( ) ) ;
311
+ }
312
+
313
+ #[ test]
314
+ fn overloaded_function_encode_by_first_signature ( ) {
315
+ let command = "ethabi encode function ../res/test.abi bar(bool) -p 1" . split ( " " ) ;
316
+ let expected = "6fae94120000000000000000000000000000000000000000000000000000000000000001" ;
317
+ assert_eq ! ( execute( command) . unwrap( ) , expected) ;
318
+ }
319
+
320
+ #[ test]
321
+ fn overloaded_function_encode_by_second_signature ( ) {
322
+ let command = "ethabi encode function ../res/test.abi bar(string):(uint256) -p 1" . split ( " " ) ;
323
+ let expected = "d473a8ed0000000000000000000000000000000000000000000000000000000000000020\
324
+ 000000000000000000000000000000000000000000000000000000000000000131000000\
325
+ 00000000000000000000000000000000000000000000000000000000";
326
+ assert_eq ! ( execute( command) . unwrap( ) , expected) ;
327
+ }
328
+
280
329
#[ test]
281
330
fn simple_decode ( ) {
282
331
let command = "ethabi decode params -t bool 0000000000000000000000000000000000000000000000000000000000000001" . split ( " " ) ;
0 commit comments