1use crate::{abi_decoder::ABIDecoder, abi_encoder::ABIEncoder, errors::Error};
2use fuels_core::{ParamType, Token};
3use hex::FromHex;
4use itertools::Itertools;
5use std::convert::TryInto;
6use std::str;
7use std::str::FromStr;
8
9use sway_types::{JsonABI, Property};
10
11use serde_json;
12
13pub struct ABIParser {
14 fn_selector: Option<Vec<u8>>,
15}
16
17impl ABIParser {
18 pub fn new() -> Self {
19 ABIParser { fn_selector: None }
20 }
21
22 pub fn encode(&mut self, abi: &str, fn_name: &str, values: &[String]) -> Result<String, Error> {
64 let parsed_abi: JsonABI = serde_json::from_str(abi)?;
65
66 let entry = parsed_abi.iter().find(|e| e.name == fn_name);
67
68 if entry.is_none() {
69 return Err(Error::InvalidName(format!(
70 "couldn't find function name: {}",
71 fn_name
72 )));
73 }
74
75 let entry = entry.unwrap();
76
77 let mut encoder = ABIEncoder::new_with_fn_selector(
78 self.build_fn_selector(fn_name, &entry.inputs)?.as_bytes(),
79 );
80
81 self.fn_selector = Some(encoder.function_selector.to_vec());
83
84 let params: Vec<_> = entry
85 .inputs
86 .iter()
87 .map(|param| parse_param(param).unwrap())
88 .zip(values.iter().map(|v| v as &str))
89 .collect();
90
91 let tokens = self.parse_tokens(¶ms)?;
92
93 Ok(hex::encode(encoder.encode(&tokens)?))
94 }
95
96 pub fn encode_with_function_selector(
137 &mut self,
138 abi: &str,
139 fn_name: &str,
140 values: &[String],
141 ) -> Result<String, Error> {
142 let encoded_params = self.encode(abi, fn_name, values)?;
143 let fn_selector = self
144 .fn_selector
145 .to_owned()
146 .expect("Function selector not encoded");
147
148 let encoded_fn_selector = hex::encode(fn_selector);
149
150 Ok(format!("{}{}", encoded_fn_selector, encoded_params))
151 }
152
153 pub fn get_encoded_function_selector(&self) -> String {
156 let fn_selector = self
157 .fn_selector
158 .to_owned()
159 .expect("Function selector not encoded");
160
161 hex::encode(fn_selector)
162 }
163
164 pub fn encode_params(&self, params: &[String]) -> Result<String, Error> {
168 let pairs: Vec<_> = params.chunks(2).collect_vec();
169
170 let mut param_type_pairs: Vec<(ParamType, &str)> = vec![];
171
172 let mut encoder = ABIEncoder::new();
173
174 for pair in pairs {
175 let prop = Property {
176 name: "".to_string(),
177 type_field: pair[0].clone(),
178 components: None,
179 };
180 let p = parse_param(&prop)?;
181
182 let t: (ParamType, &str) = (p, &pair[1]);
183 param_type_pairs.push(t);
184 }
185
186 let tokens = self.parse_tokens(¶m_type_pairs)?;
187
188 let encoded = encoder.encode(&tokens)?;
189
190 Ok(hex::encode(encoded))
191 }
192
193 pub fn parse_tokens<'a>(&self, params: &'a [(ParamType, &str)]) -> Result<Vec<Token>, Error> {
197 params
198 .iter()
199 .map(|&(ref param, value)| self.tokenize(param, value.to_string()))
200 .collect::<Result<_, _>>()
201 .map_err(From::from)
202 }
203
204 pub fn tokenize<'a>(&self, param: &ParamType, value: String) -> Result<Token, Error> {
208 let trimmed_value = value.trim();
209 match &*param {
210 ParamType::U8 => Ok(Token::U8(trimmed_value.parse::<u8>()?)),
211 ParamType::U16 => Ok(Token::U16(trimmed_value.parse::<u16>()?)),
212 ParamType::U32 => Ok(Token::U32(trimmed_value.parse::<u32>()?)),
213 ParamType::U64 => Ok(Token::U64(trimmed_value.parse::<u64>()?)),
214 ParamType::Bool => Ok(Token::Bool(trimmed_value.parse::<bool>()?)),
215 ParamType::Byte => Ok(Token::Byte(trimmed_value.parse::<u8>()?)),
216 ParamType::B256 => {
217 let v = Vec::from_hex(trimmed_value)?;
218 let s: [u8; 32] = v.as_slice().try_into().unwrap();
219 Ok(Token::B256(s))
220 }
221 ParamType::Array(t, _) => Ok(self.tokenize_array(trimmed_value, &*t)?),
222 ParamType::String(_) => Ok(Token::String(trimmed_value.to_string())),
223 ParamType::Struct(struct_params) => {
224 Ok(self.tokenize_struct(trimmed_value, struct_params)?)
225 }
226 ParamType::Enum(s) => {
227 let discriminant = self.get_enum_discriminant_from_string(&value);
228 let value = self.get_enum_value_from_string(&value);
229
230 let token = self.tokenize(&s[discriminant], value)?;
231
232 Ok(Token::Enum(Box::new((discriminant as u8, token))))
233 }
234 }
235 }
236
237 pub fn tokenize_struct(&self, value: &str, params: &[ParamType]) -> Result<Token, Error> {
244 if !value.starts_with('(') || !value.ends_with(')') {
245 return Err(Error::InvalidData);
246 }
247
248 if value.chars().count() == 2 {
249 return Ok(Token::Struct(vec![]));
250 }
251
252 let mut result = vec![];
253 let mut nested = 0isize;
254 let mut ignore = false;
255 let mut last_item = 1;
256 let mut params_iter = params.iter();
257
258 for (pos, ch) in value.chars().enumerate() {
259 match ch {
260 '(' if !ignore => {
261 nested += 1;
262 }
263 ')' if !ignore => {
264 nested -= 1;
265
266 match nested.cmp(&0) {
267 std::cmp::Ordering::Less => {
268 return Err(Error::InvalidData);
269 }
270 std::cmp::Ordering::Equal => {
271 let sub = &value[last_item..pos];
272
273 let token = self.tokenize(
274 params_iter.next().ok_or(Error::InvalidData)?,
275 sub.to_string(),
276 )?;
277 result.push(token);
278 last_item = pos + 1;
279 }
280 _ => {}
281 }
282 }
283 '"' => {
284 ignore = !ignore;
285 }
286 ',' if nested == 1 && !ignore => {
287 let sub = &value[last_item..pos];
288 if sub.contains('[') && !sub.contains(']') {
291 continue;
292 }
293
294 let token = self.tokenize(
295 params_iter.next().ok_or(Error::InvalidData)?,
296 sub.to_string(),
297 )?;
298 result.push(token);
299 last_item = pos + 1;
300 }
301 _ => (),
302 }
303 }
304
305 if ignore {
306 return Err(Error::InvalidData);
307 }
308
309 Ok(Token::Struct(result))
310 }
311
312 pub fn tokenize_array<'a>(&self, value: &'a str, param: &ParamType) -> Result<Token, Error> {
319 if !value.starts_with('[') || !value.ends_with(']') {
320 return Err(Error::InvalidData);
321 }
322
323 if value.chars().count() == 2 {
324 return Ok(Token::Array(vec![]));
325 }
326
327 let mut result = vec![];
328 let mut nested = 0isize;
329 let mut ignore = false;
330 let mut last_item = 1;
331 for (i, ch) in value.chars().enumerate() {
332 match ch {
333 '[' if !ignore => {
334 nested += 1;
335 }
336 ']' if !ignore => {
337 nested -= 1;
338
339 match nested.cmp(&0) {
340 std::cmp::Ordering::Less => {
341 return Err(Error::InvalidData);
342 }
343 std::cmp::Ordering::Equal => {
344 let sub = &value[last_item..i];
346 match self.is_array(sub) {
347 true => {
348 let arr_param = ParamType::Array(
349 Box::new(param.to_owned()),
350 self.get_array_length_from_string(sub),
351 );
352
353 result.push(self.tokenize(&arr_param, sub.to_string())?);
354 }
355 false => {
356 result.push(self.tokenize(param, sub.to_string())?);
357 }
358 }
359
360 last_item = i + 1;
361 }
362 _ => {}
363 }
364 }
365 '"' => {
366 ignore = !ignore;
367 }
368 ',' if nested == 1 && !ignore => {
369 let sub = &value[last_item..i];
370 match self.is_array(sub) {
371 true => {
372 let arr_param = ParamType::Array(
373 Box::new(param.to_owned()),
374 self.get_array_length_from_string(sub),
375 );
376
377 result.push(self.tokenize(&arr_param, sub.to_string())?);
378 }
379 false => {
380 result.push(self.tokenize(param, sub.to_string())?);
381 }
382 }
383 last_item = i + 1;
384 }
385 _ => (),
386 }
387 }
388
389 if ignore {
390 return Err(Error::InvalidData);
391 }
392
393 Ok(Token::Array(result))
394 }
395
396 pub fn decode<'a>(
401 &self,
402 abi: &str,
403 fn_name: &str,
404 value: &'a [u8],
405 ) -> Result<Vec<Token>, Error> {
406 let parsed_abi: JsonABI = serde_json::from_str(abi)?;
407
408 let entry = parsed_abi.iter().find(|e| e.name == fn_name);
409
410 if entry.is_none() {
411 return Err(Error::InvalidName(format!(
412 "couldn't find function name: {}",
413 fn_name
414 )));
415 }
416
417 let params_result: Result<Vec<_>, _> = entry
418 .unwrap()
419 .outputs
420 .iter()
421 .map(|param| parse_param(param))
422 .collect();
423
424 match params_result {
425 Ok(params) => {
426 let mut decoder = ABIDecoder::new();
427
428 Ok(decoder.decode(¶ms, value)?)
429 }
430 Err(e) => Err(e),
431 }
432 }
433
434 pub fn decode_params(&self, params: &[ParamType], data: &[u8]) -> Result<Vec<Token>, Error> {
437 let mut decoder = ABIDecoder::new();
438 Ok(decoder.decode(params, data)?)
439 }
440
441 fn is_array(&self, ele: &str) -> bool {
442 ele.starts_with('[') && ele.ends_with(']')
443 }
444
445 fn get_enum_discriminant_from_string(&self, ele: &str) -> usize {
446 let mut chars = ele.chars();
447 chars.next(); chars.next_back(); let v: Vec<_> = chars.as_str().split(',').collect();
450 v[0].parse().unwrap()
451 }
452
453 fn get_enum_value_from_string(&self, ele: &str) -> String {
454 let mut chars = ele.chars();
455 chars.next(); chars.next_back(); let v: Vec<_> = chars.as_str().split(',').collect();
458 v[1].to_string()
459 }
460
461 fn get_array_length_from_string(&self, ele: &str) -> usize {
462 let mut chars = ele.chars();
463 chars.next();
464 chars.next_back();
465 chars.as_str().split(',').count()
466 }
467
468 pub fn build_fn_selector(&self, fn_name: &str, params: &[Property]) -> Result<String, Error> {
471 let fn_selector = fn_name.to_owned();
472
473 let mut result: String = format!("{}(", fn_selector);
474
475 for (idx, param) in params.iter().enumerate() {
476 result.push_str(&self.build_fn_selector_params(param));
477 if idx + 1 < params.len() {
478 result.push(',');
479 }
480 }
481
482 result.push(')');
483
484 Ok(result)
485 }
486
487 fn build_fn_selector_params(&self, param: &Property) -> String {
488 let mut result: String = String::new();
489
490 if param.type_field.contains("struct ") || param.type_field.contains("enum ") {
491 result.push_str("s(");
494
495 for (idx, component) in param.components.as_ref().unwrap().iter().enumerate() {
496 let res = self.build_fn_selector_params(component);
497 result.push_str(&res);
498
499 if idx + 1 < param.components.as_ref().unwrap().len() {
500 result.push(',');
501 }
502 }
503 result.push(')');
504 } else {
505 result.push_str(¶m.type_field);
506 }
507 result
508 }
509}
510
511pub fn parse_param(param: &Property) -> Result<ParamType, Error> {
513 match ParamType::from_str(¶m.type_field) {
514 Ok(param_type) => Ok(param_type),
516 Err(_) => {
517 match param.type_field.contains("struct") || param.type_field.contains("enum") {
518 true => Ok(parse_custom_type_param(param)?),
519 false => {
520 match param.type_field.contains('[') && param.type_field.contains(']') {
521 true => Ok(parse_array_param(param)?),
523 false => Ok(parse_custom_type_param(param)?),
525 }
526 }
527 }
528 }
529 }
530}
531
532pub fn parse_array_param(param: &Property) -> Result<ParamType, Error> {
533 let split: Vec<&str> = param.type_field.split('[').collect();
535 if split.len() != 2 {
536 return Err(Error::MissingData(format!(
537 "invalid parameter type: {}",
538 param.type_field
539 )));
540 }
541
542 let param_type = ParamType::from_str(split[0]).unwrap();
543
544 let size: usize = split[1][..split[1].len() - 1].parse().unwrap();
546
547 if let ParamType::String(_) = param_type {
548 Ok(ParamType::String(size))
549 } else {
550 Ok(ParamType::Array(Box::new(param_type), size))
551 }
552}
553
554pub fn parse_custom_type_param(param: &Property) -> Result<ParamType, Error> {
555 let mut params: Vec<ParamType> = vec![];
556
557 match param.components.as_ref() {
558 Some(components) => {
559 for component in components {
560 params.push(parse_param(component)?)
561 }
562 }
563 None => {
564 return Err(Error::MissingData(
565 "cannot parse custom type with no components".into(),
566 ))
567 }
568 }
569
570 if param.type_field.contains("struct") {
571 return Ok(ParamType::Struct(params));
572 }
573 if param.type_field.contains("enum") {
574 return Ok(ParamType::Enum(params));
575 }
576 Err(Error::InvalidType(param.type_field.clone()))
577}
578
579#[cfg(test)]
580mod tests {
581 use super::*;
582
583 #[test]
584 fn simple_encode_and_decode_no_selector() {
585 let json_abi = r#"
586 [
587 {
588 "type":"contract",
589 "inputs":[
590 {
591 "name":"arg",
592 "type":"u32"
593 }
594 ],
595 "name":"takes_u32_returns_bool",
596 "outputs":[
597 {
598 "name":"",
599 "type":"bool"
600 }
601 ]
602 }
603 ]
604 "#;
605
606 let values: Vec<String> = vec!["10".to_string()];
607
608 let mut abi = ABIParser::new();
609
610 let function_name = "takes_u32_returns_bool";
611
612 let encoded = abi.encode(json_abi, function_name, &values).unwrap();
613 println!("encoded: {:?}\n", encoded);
614
615 let expected_encode = "000000000000000a";
616 assert_eq!(encoded, expected_encode);
617
618 let return_value = [
619 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ];
621
622 let decoded_return = abi.decode(json_abi, function_name, &return_value).unwrap();
623
624 let expected_return = vec![Token::Bool(false)];
625
626 assert_eq!(decoded_return, expected_return);
627 }
628
629 #[test]
630 fn simple_encode_and_decode() {
631 let json_abi = r#"
632 [
633 {
634 "type":"contract",
635 "inputs":[
636 {
637 "name":"arg",
638 "type":"u32"
639 }
640 ],
641 "name":"takes_u32_returns_bool",
642 "outputs":[
643 {
644 "name":"",
645 "type":"bool"
646 }
647 ]
648 }
649 ]
650 "#;
651
652 let values: Vec<String> = vec!["10".to_string()];
653
654 let mut abi = ABIParser::new();
655
656 let function_name = "takes_u32_returns_bool";
657
658 let encoded = abi
659 .encode_with_function_selector(json_abi, function_name, &values)
660 .unwrap();
661 println!("encoded: {:?}\n", encoded);
662
663 let expected_encode = "000000006355e6ee000000000000000a";
664 assert_eq!(encoded, expected_encode);
665
666 let return_value = [
667 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ];
669
670 let decoded_return = abi.decode(json_abi, function_name, &return_value).unwrap();
671
672 let expected_return = vec![Token::Bool(false)];
673
674 assert_eq!(decoded_return, expected_return);
675 }
676
677 #[test]
678 fn b256_and_single_byte_encode_and_decode() {
679 let json_abi = r#"
680 [
681 {
682 "type":"contract",
683 "inputs":[
684 {
685 "name":"foo",
686 "type":"b256"
687 },
688 {
689 "name":"bar",
690 "type":"byte"
691 }
692 ],
693 "name":"my_func",
694 "outputs":[
695 {
696 "name":"",
697 "type":"b256"
698 }
699 ]
700 }
701 ]
702 "#;
703
704 let values: Vec<String> = vec![
705 "d5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b".to_string(),
706 "1".to_string(),
707 ];
708
709 let mut abi = ABIParser::new();
710
711 let function_name = "my_func";
712
713 let encoded = abi
714 .encode_with_function_selector(json_abi, function_name, &values)
715 .unwrap();
716 println!("encoded: {:?}\n", encoded);
717
718 let expected_encode = "00000000e64019abd5579c46dfcc7f18207013e65b44e4cb4e2c2298f4ac457ba8f82743f31e930b0000000000000001";
719 assert_eq!(encoded, expected_encode);
720
721 let return_value =
722 hex::decode("a441b15fe9a3cf56661190a0b93b9dec7d04127288cc87250967cf3b52894d11")
723 .unwrap();
724
725 let decoded_return = abi.decode(json_abi, function_name, &return_value).unwrap();
726
727 let s: [u8; 32] = return_value.as_slice().try_into().unwrap();
728
729 let expected_return = vec![Token::B256(s)];
730
731 assert_eq!(decoded_return, expected_return);
732 }
733
734 #[test]
735 fn array_encode_and_decode() {
736 let json_abi = r#"
737 [
738 {
739 "type":"contract",
740 "inputs":[
741 {
742 "name":"arg",
743 "type":"u16[3]"
744 }
745 ],
746 "name":"takes_array",
747 "outputs":[
748 {
749 "name":"",
750 "type":"u16[2]"
751 }
752 ]
753 }
754 ]
755 "#;
756
757 let values: Vec<String> = vec!["[1,2,3]".to_string()];
758
759 let mut abi = ABIParser::new();
760
761 let function_name = "takes_array";
762
763 let encoded = abi
764 .encode_with_function_selector(json_abi, function_name, &values)
765 .unwrap();
766 println!("encoded: {:?}\n", encoded);
767
768 let expected_encode = "00000000f0b87864000000000000000100000000000000020000000000000003";
769 assert_eq!(encoded, expected_encode);
770
771 let return_value = [
772 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, ];
775
776 let decoded_return = abi.decode(json_abi, function_name, &return_value).unwrap();
777
778 let expected_return = vec![Token::Array(vec![Token::U16(0), Token::U16(1)])];
779
780 assert_eq!(decoded_return, expected_return);
781 }
782
783 #[test]
784 fn tokenize_array() {
785 let abi = ABIParser::new();
786
787 let value = "[[1,2],[3],4]";
788 let param = ParamType::U16;
789 let tokens = abi.tokenize_array(value, ¶m).unwrap();
790
791 let expected_tokens = Token::Array(vec![
792 Token::Array(vec![Token::U16(1), Token::U16(2)]), Token::Array(vec![Token::U16(3)]), Token::U16(4), ]);
796
797 assert_eq!(tokens, expected_tokens);
798
799 let value = "[1,[2],[3],[4,5]]";
800 let param = ParamType::U16;
801 let tokens = abi.tokenize_array(value, ¶m).unwrap();
802
803 let expected_tokens = Token::Array(vec![
804 Token::U16(1),
805 Token::Array(vec![Token::U16(2)]),
806 Token::Array(vec![Token::U16(3)]),
807 Token::Array(vec![Token::U16(4), Token::U16(5)]),
808 ]);
809
810 assert_eq!(tokens, expected_tokens);
811
812 let value = "[1,2,3,4,5]";
813 let param = ParamType::U16;
814 let tokens = abi.tokenize_array(value, ¶m).unwrap();
815
816 let expected_tokens = Token::Array(vec![
817 Token::U16(1),
818 Token::U16(2),
819 Token::U16(3),
820 Token::U16(4),
821 Token::U16(5),
822 ]);
823
824 assert_eq!(tokens, expected_tokens);
825
826 let value = "[[1,2,3,[4,5]]]";
827 let param = ParamType::U16;
828 let tokens = abi.tokenize_array(value, ¶m).unwrap();
829
830 let expected_tokens = Token::Array(vec![Token::Array(vec![
831 Token::U16(1),
832 Token::U16(2),
833 Token::U16(3),
834 Token::Array(vec![Token::U16(4), Token::U16(5)]),
835 ])]);
836
837 assert_eq!(tokens, expected_tokens);
838 }
839
840 #[test]
841 fn nested_array_encode_and_decode() {
842 let json_abi = r#"
843 [
844 {
845 "type":"contract",
846 "inputs":[
847 {
848 "name":"arg",
849 "type":"u16[3]"
850 }
851 ],
852 "name":"takes_nested_array",
853 "outputs":[
854 {
855 "name":"",
856 "type":"u16[2]"
857 }
858 ]
859 }
860 ]
861 "#;
862
863 let values: Vec<String> = vec!["[[1,2],[3],[4]]".to_string()];
864
865 let mut abi = ABIParser::new();
866
867 let function_name = "takes_nested_array";
868
869 let encoded = abi
870 .encode_with_function_selector(json_abi, function_name, &values)
871 .unwrap();
872 println!("encoded: {:?}\n", encoded);
873
874 let expected_encode =
875 "00000000e5d521030000000000000001000000000000000200000000000000030000000000000004";
876 assert_eq!(encoded, expected_encode);
877
878 let return_value = [
879 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, ];
882
883 let decoded_return = abi.decode(json_abi, function_name, &return_value).unwrap();
884
885 let expected_return = vec![Token::Array(vec![Token::U16(0), Token::U16(1)])];
886
887 assert_eq!(decoded_return, expected_return);
888 }
889
890 #[test]
891 fn string_encode_and_decode() {
892 let json_abi = r#"
893 [
894 {
895 "type":"contract",
896 "inputs":[
897 {
898 "name":"foo",
899 "type":"str[23]"
900 }
901 ],
902 "name":"takes_string",
903 "outputs":[
904 {
905 "name":"",
906 "type":"str[2]"
907 }
908 ]
909 }
910 ]
911 "#;
912
913 let values: Vec<String> = vec!["This is a full sentence".to_string()];
914
915 let mut abi = ABIParser::new();
916
917 let function_name = "takes_string";
918
919 let encoded = abi
920 .encode_with_function_selector(json_abi, function_name, &values)
921 .unwrap();
922 println!("encoded: {:?}\n", encoded);
923
924 let expected_encode = "00000000d56e76515468697320697320612066756c6c2073656e74656e636500";
925 assert_eq!(encoded, expected_encode);
926
927 let return_value = [
928 0x4f, 0x4b, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ];
930
931 let decoded_return = abi.decode(json_abi, function_name, &return_value).unwrap();
932
933 let expected_return = vec![Token::String("OK".into())];
934
935 assert_eq!(decoded_return, expected_return);
936 }
937
938 #[test]
939 fn struct_encode_and_decode() {
940 let json_abi = r#"
941 [
942 {
943 "type":"contract",
944 "inputs":[
945 {
946 "name":"my_struct",
947 "type":"struct MyStruct",
948 "components": [
949 {
950 "name": "foo",
951 "type": "u8"
952 },
953 {
954 "name": "bar",
955 "type": "bool"
956 }
957 ]
958 }
959 ],
960 "name":"takes_struct",
961 "outputs":[]
962 }
963 ]
964 "#;
965
966 let values: Vec<String> = vec!["(42, true)".to_string()];
967
968 let mut abi = ABIParser::new();
969
970 let function_name = "takes_struct";
971
972 let encoded = abi
973 .encode_with_function_selector(json_abi, function_name, &values)
974 .unwrap();
975 println!("encoded: {:?}\n", encoded);
976
977 let expected_encode = "00000000cb0b2f05000000000000002a0000000000000001";
978 assert_eq!(encoded, expected_encode);
979 }
980
981 #[test]
982 fn struct_and_primitive_encode_and_decode() {
983 let json_abi = r#"
984 [
985 {
986 "type":"contract",
987 "inputs":[
988 {
989 "name":"my_struct",
990 "type":"struct MyStruct",
991 "components": [
992 {
993 "name": "foo",
994 "type": "u8"
995 },
996 {
997 "name": "bar",
998 "type": "bool"
999 }
1000 ]
1001 },
1002 {
1003 "name":"foo",
1004 "type":"u32"
1005 }
1006 ],
1007 "name":"takes_struct_and_primitive",
1008 "outputs":[]
1009 }
1010 ]
1011 "#;
1012
1013 let values: Vec<String> = vec!["(42, true)".to_string(), "10".to_string()];
1014
1015 let mut abi = ABIParser::new();
1016
1017 let function_name = "takes_struct_and_primitive";
1018
1019 let encoded = abi
1020 .encode_with_function_selector(json_abi, function_name, &values)
1021 .unwrap();
1022 println!("encoded: {:?}\n", encoded);
1023
1024 let expected_encode = "000000005c445838000000000000002a0000000000000001000000000000000a";
1025 assert_eq!(encoded, expected_encode);
1026 }
1027
1028 #[test]
1029 fn nested_struct_encode_and_decode() {
1030 let json_abi = r#"
1031 [
1032 {
1033 "type":"contract",
1034 "inputs":[
1035 {
1036 "name":"top_value",
1037 "type":"struct MyNestedStruct",
1038 "components": [
1039 {
1040 "name": "x",
1041 "type": "u16"
1042 },
1043 {
1044 "name": "inner",
1045 "type": "struct Y",
1046 "components": [
1047 {
1048 "name":"a",
1049 "type": "bool"
1050 },
1051 {
1052 "name":"b",
1053 "type": "u8[2]"
1054 }
1055 ]
1056 }
1057 ]
1058 }
1059 ],
1060 "name":"takes_nested_struct",
1061 "outputs":[]
1062 }
1063 ]
1064 "#;
1065
1066 let values: Vec<String> = vec!["(10, (true, [1,2]))".to_string()];
1067
1068 let mut abi = ABIParser::new();
1069
1070 let function_name = "takes_nested_struct";
1071
1072 let encoded = abi
1073 .encode_with_function_selector(json_abi, function_name, &values)
1074 .unwrap();
1075 println!("encoded: {:?}\n", encoded);
1076
1077 let expected_encode =
1078 "00000000ff25eb48000000000000000a000000000000000100000000000000010000000000000002";
1079 assert_eq!(encoded, expected_encode);
1080
1081 let json_abi = r#"
1082 [
1083 {
1084 "type":"contract",
1085 "inputs":[
1086 {
1087 "name":"top_value",
1088 "type":"struct MyNestedStruct",
1089 "components": [
1090 {
1091 "name": "inner",
1092 "type": "struct X",
1093 "components": [
1094 {
1095 "name":"a",
1096 "type": "bool"
1097 },
1098 {
1099 "name":"b",
1100 "type": "u8[2]"
1101 }
1102 ]
1103 },
1104 {
1105 "name": "y",
1106 "type": "u16"
1107 }
1108 ]
1109 }
1110 ],
1111 "name":"takes_nested_struct",
1112 "outputs":[]
1113 }
1114 ]
1115 "#;
1116
1117 let values: Vec<String> = vec!["((true, [1,2]), 10)".to_string()];
1118
1119 let encoded = abi
1120 .encode_with_function_selector(json_abi, function_name, &values)
1121 .unwrap();
1122 println!("encoded: {:?}\n", encoded);
1123
1124 let expected_encode =
1125 "000000007728cb9e000000000000000100000000000000010000000000000002000000000000000a";
1126 assert_eq!(encoded, expected_encode);
1127 }
1128
1129 #[test]
1130 fn enum_encode_and_decode() {
1131 let json_abi = r#"
1132 [
1133 {
1134 "type":"contract",
1135 "inputs":[
1136 {
1137 "name":"my_enum",
1138 "type":"enum MyEnum",
1139 "components": [
1140 {
1141 "name": "x",
1142 "type": "u32"
1143 },
1144 {
1145 "name": "y",
1146 "type": "bool"
1147 }
1148 ]
1149 }
1150 ],
1151 "name":"takes_enum",
1152 "outputs":[]
1153 }
1154 ]
1155 "#;
1156
1157 let values: Vec<String> = vec!["(0, 42)".to_string()];
1158
1159 let mut abi = ABIParser::new();
1160
1161 let function_name = "takes_enum";
1162
1163 let encoded = abi
1164 .encode_with_function_selector(json_abi, function_name, &values)
1165 .unwrap();
1166 println!("encoded: {:?}\n", encoded);
1167
1168 let expected_encode = "00000000082e0dfa0000000000000000000000000000002a";
1169 assert_eq!(encoded, expected_encode);
1170 }
1171
1172 #[test]
1173 fn fn_selector_single_primitive() {
1174 let abi = ABIParser::new();
1175 let p = Property {
1176 name: "foo".into(),
1177 type_field: "u64".into(),
1178 components: None,
1179 };
1180 let params = vec![p];
1181 let selector = abi.build_fn_selector("my_func", ¶ms).unwrap();
1182
1183 assert_eq!(selector, "my_func(u64)");
1184 }
1185
1186 #[test]
1187 fn fn_selector_multiple_primitives() {
1188 let abi = ABIParser::new();
1189 let p1 = Property {
1190 name: "foo".into(),
1191 type_field: "u64".into(),
1192 components: None,
1193 };
1194 let p2 = Property {
1195 name: "bar".into(),
1196 type_field: "bool".into(),
1197 components: None,
1198 };
1199 let params = vec![p1, p2];
1200 let selector = abi.build_fn_selector("my_func", ¶ms).unwrap();
1201
1202 assert_eq!(selector, "my_func(u64,bool)");
1203 }
1204
1205 #[test]
1206 fn fn_selector_custom_type() {
1207 let abi = ABIParser::new();
1208
1209 let inner_foo = Property {
1210 name: "foo".into(),
1211 type_field: "bool".into(),
1212 components: None,
1213 };
1214
1215 let inner_bar = Property {
1216 name: "bar".into(),
1217 type_field: "u64".into(),
1218 components: None,
1219 };
1220
1221 let p = Property {
1222 name: "my_struct".into(),
1223 type_field: "struct MyStruct".into(),
1224 components: Some(vec![inner_foo, inner_bar]),
1225 };
1226
1227 let params = vec![p];
1228 let selector = abi.build_fn_selector("my_func", ¶ms).unwrap();
1229
1230 assert_eq!(selector, "my_func(s(bool,u64))");
1231 }
1232
1233 #[test]
1234 fn fn_selector_nested_custom_type() {
1235 let abi = ABIParser::new();
1236
1237 let inner_foo = Property {
1238 name: "foo".into(),
1239 type_field: "bool".into(),
1240 components: None,
1241 };
1242
1243 let inner_a = Property {
1244 name: "a".into(),
1245 type_field: "u64".into(),
1246 components: None,
1247 };
1248
1249 let inner_b = Property {
1250 name: "b".into(),
1251 type_field: "u32".into(),
1252 components: None,
1253 };
1254
1255 let inner_bar = Property {
1256 name: "bar".into(),
1257 type_field: "struct InnerStruct".into(),
1258 components: Some(vec![inner_a, inner_b]),
1259 };
1260
1261 let p = Property {
1262 name: "my_struct".into(),
1263 type_field: "struct MyStruct".into(),
1264 components: Some(vec![inner_foo, inner_bar]),
1265 };
1266
1267 let params = vec![p];
1268 println!("params: {:?}\n", params);
1269 let selector = abi.build_fn_selector("my_func", ¶ms).unwrap();
1270
1271 assert_eq!(selector, "my_func(s(bool,s(u64,u32)))");
1272 }
1273
1274 #[test]
1275 fn compiler_generated_abi_test() {
1276 let json_abi = r#"
1277 [
1278 {
1279 "inputs": [
1280 {
1281 "components": null,
1282 "name": "gas_",
1283 "type": "u64"
1284 },
1285 {
1286 "components": null,
1287 "name": "amount_",
1288 "type": "u64"
1289 },
1290 {
1291 "components": null,
1292 "name": "color_",
1293 "type": "b256"
1294 },
1295 {
1296 "components": null,
1297 "name": "value",
1298 "type": "u64"
1299 }
1300 ],
1301 "name": "foo",
1302 "outputs": [
1303 {
1304 "components": null,
1305 "name": "",
1306 "type": "u64"
1307 }
1308 ],
1309 "type": "function"
1310 },
1311 {
1312 "inputs": [
1313 {
1314 "components": null,
1315 "name": "gas_",
1316 "type": "u64"
1317 },
1318 {
1319 "components": null,
1320 "name": "amount_",
1321 "type": "u64"
1322 },
1323 {
1324 "components": null,
1325 "name": "color_",
1326 "type": "b256"
1327 },
1328 {
1329 "components": [
1330 {
1331 "components": null,
1332 "name": "a",
1333 "type": "bool"
1334 },
1335 {
1336 "components": null,
1337 "name": "b",
1338 "type": "u64"
1339 }
1340 ],
1341 "name": "value",
1342 "type": "struct TestStruct"
1343 }
1344 ],
1345 "name": "boo",
1346 "outputs": [
1347 {
1348 "components": [
1349 {
1350 "components": null,
1351 "name": "a",
1352 "type": "bool"
1353 },
1354 {
1355 "components": null,
1356 "name": "b",
1357 "type": "u64"
1358 }
1359 ],
1360 "name": "",
1361 "type": "struct TestStruct"
1362 }
1363 ],
1364 "type": "function"
1365 }
1366 ]
1367 "#;
1368
1369 let gas = "1000000".to_string();
1370 let coins = "0".to_string();
1371 let color = "0000000000000000000000000000000000000000000000000000000000000000".to_string();
1372 let s = "(true, 42)".to_string();
1373
1374 let values: Vec<String> = vec![gas, coins, color, s];
1375
1376 let mut abi = ABIParser::new();
1377
1378 let function_name = "boo";
1379
1380 let encoded = abi
1381 .encode_with_function_selector(json_abi, function_name, &values)
1382 .unwrap();
1383 println!("encoded: {:?}\n", encoded);
1384
1385 let expected_encode = "0000000087f27a3900000000000f4240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000002a";
1386 assert_eq!(encoded, expected_encode);
1387 }
1388}