1mod buffer;
2mod checkers;
3mod decoder;
4mod encoder;
5mod selectors;
6mod storage_layout;
7mod types;
8
9pub use buffer::{buffer_as_fields, buffer_from_fields};
11pub use checkers::{
12 abi_checker, abi_type_size, count_arguments_size, is_address_struct, is_aztec_address_struct,
13 is_bounded_vec_struct, is_eth_address_struct, is_function_selector_struct, is_option_struct,
14 is_public_keys_struct, is_wrapped_field_struct,
15};
16pub use decoder::{decode_from_abi, AbiDecoded};
17pub use encoder::{encode_arguments, encode_value};
18pub use selectors::{AuthorizationSelector, EventSelector, FunctionSelector, NoteSelector};
19pub use storage_layout::{ContractStorageLayout, FieldLayout};
20pub use types::{
21 abi_type_signature, AbiParameter, AbiType, AbiValue, ContractArtifact, FunctionArtifact,
22 FunctionType,
23};
24
25#[cfg(test)]
26#[allow(clippy::expect_used, clippy::panic)]
27mod tests {
28 use super::*;
29 use std::collections::BTreeMap;
30
31 use crate::types::Fr;
32
33 const MINIMAL_ARTIFACT: &str = r#"
34 {
35 "name": "TestContract",
36 "functions": [
37 {
38 "name": "increment",
39 "function_type": "public",
40 "is_initializer": false,
41 "is_static": false,
42 "parameters": [
43 { "name": "value", "type": { "kind": "field" } }
44 ],
45 "return_types": []
46 }
47 ]
48 }
49 "#;
50
51 const MULTI_FUNCTION_ARTIFACT: &str = r#"
52 {
53 "name": "TokenContract",
54 "functions": [
55 {
56 "name": "constructor",
57 "function_type": "private",
58 "is_initializer": true,
59 "is_static": false,
60 "parameters": [
61 { "name": "admin", "type": { "kind": "field" } },
62 { "name": "name", "type": { "kind": "string", "length": 31 } }
63 ],
64 "return_types": []
65 },
66 {
67 "name": "transfer",
68 "function_type": "private",
69 "is_initializer": false,
70 "is_static": false,
71 "parameters": [
72 { "name": "from", "type": { "kind": "field" } },
73 { "name": "to", "type": { "kind": "field" } },
74 { "name": "amount", "type": { "kind": "integer", "sign": "unsigned", "width": 64 } }
75 ],
76 "return_types": []
77 },
78 {
79 "name": "balance_of",
80 "function_type": "utility",
81 "is_initializer": false,
82 "is_static": true,
83 "parameters": [
84 { "name": "owner", "type": { "kind": "field" } }
85 ],
86 "return_types": [
87 { "kind": "integer", "sign": "unsigned", "width": 64 }
88 ]
89 },
90 {
91 "name": "total_supply",
92 "function_type": "public",
93 "is_initializer": false,
94 "is_static": true,
95 "parameters": [],
96 "return_types": [
97 { "kind": "integer", "sign": "unsigned", "width": 64 }
98 ]
99 }
100 ]
101 }
102 "#;
103
104 #[test]
105 fn function_type_roundtrip() {
106 for (ft, expected) in [
107 (FunctionType::Private, "\"private\""),
108 (FunctionType::Public, "\"public\""),
109 (FunctionType::Utility, "\"utility\""),
110 ] {
111 let json = serde_json::to_string(&ft).expect("serialize FunctionType");
112 assert_eq!(json, expected);
113 let decoded: FunctionType =
114 serde_json::from_str(&json).expect("deserialize FunctionType");
115 assert_eq!(decoded, ft);
116 }
117 }
118
119 #[test]
120 fn function_selector_hex_roundtrip() {
121 let selector = FunctionSelector::from_hex("0xaabbccdd").expect("valid hex");
122 assert_eq!(selector.0, [0xaa, 0xbb, 0xcc, 0xdd]);
123 assert_eq!(selector.to_string(), "0xaabbccdd");
124
125 let json = serde_json::to_string(&selector).expect("serialize selector");
126 let decoded: FunctionSelector = serde_json::from_str(&json).expect("deserialize selector");
127 assert_eq!(decoded, selector);
128 }
129
130 #[test]
131 fn authorization_selector_hex_roundtrip() {
132 let selector = AuthorizationSelector::from_hex("0x01020304").expect("valid hex");
133 assert_eq!(selector.0, [0x01, 0x02, 0x03, 0x04]);
134 assert_eq!(selector.to_string(), "0x01020304");
135
136 let json = serde_json::to_string(&selector).expect("serialize selector");
137 let decoded: AuthorizationSelector =
138 serde_json::from_str(&json).expect("deserialize selector");
139 assert_eq!(decoded, selector);
140 }
141
142 #[test]
143 fn function_selector_rejects_too_long() {
144 let result = FunctionSelector::from_hex("0xaabbccddee");
145 assert!(result.is_err());
146 }
147
148 #[test]
149 fn event_selector_roundtrip() {
150 let selector = EventSelector(Fr::from(42u64));
151 let json = serde_json::to_string(&selector).expect("serialize EventSelector");
152 let decoded: EventSelector =
153 serde_json::from_str(&json).expect("deserialize EventSelector");
154 assert_eq!(decoded, selector);
155 }
156
157 #[test]
158 fn load_minimal_artifact() {
159 let artifact = ContractArtifact::from_json(MINIMAL_ARTIFACT).expect("parse artifact");
160 assert_eq!(artifact.name, "TestContract");
161 assert_eq!(artifact.functions.len(), 1);
162 assert_eq!(artifact.functions[0].name, "increment");
163 assert_eq!(artifact.functions[0].function_type, FunctionType::Public);
164 assert!(!artifact.functions[0].is_initializer);
165 assert_eq!(artifact.functions[0].parameters.len(), 1);
166 assert_eq!(artifact.functions[0].parameters[0].name, "value");
167 }
168
169 #[test]
170 fn load_multi_function_artifact() {
171 let artifact =
172 ContractArtifact::from_json(MULTI_FUNCTION_ARTIFACT).expect("parse artifact");
173 assert_eq!(artifact.name, "TokenContract");
174 assert_eq!(artifact.functions.len(), 4);
175
176 let constructor = &artifact.functions[0];
177 assert_eq!(constructor.name, "constructor");
178 assert_eq!(constructor.function_type, FunctionType::Private);
179 assert!(constructor.is_initializer);
180 assert_eq!(constructor.parameters.len(), 2);
181
182 let transfer = &artifact.functions[1];
183 assert_eq!(transfer.name, "transfer");
184 assert_eq!(transfer.function_type, FunctionType::Private);
185 assert!(!transfer.is_static);
186
187 let balance = &artifact.functions[2];
188 assert_eq!(balance.name, "balance_of");
189 assert_eq!(balance.function_type, FunctionType::Utility);
190 assert!(balance.is_static);
191 assert_eq!(balance.return_types.len(), 1);
192
193 let supply = &artifact.functions[3];
194 assert_eq!(supply.name, "total_supply");
195 assert_eq!(supply.function_type, FunctionType::Public);
196 assert!(supply.is_static);
197 }
198
199 #[test]
200 fn find_function_by_name() {
201 let artifact =
202 ContractArtifact::from_json(MULTI_FUNCTION_ARTIFACT).expect("parse artifact");
203
204 let transfer = artifact.find_function("transfer").expect("find transfer");
205 assert_eq!(transfer.name, "transfer");
206 assert_eq!(transfer.function_type, FunctionType::Private);
207 }
208
209 #[test]
210 fn find_function_not_found() {
211 let artifact =
212 ContractArtifact::from_json(MULTI_FUNCTION_ARTIFACT).expect("parse artifact");
213
214 let result = artifact.find_function("nonexistent");
215 assert!(result.is_err());
216 }
217
218 #[test]
219 fn find_function_by_type() {
220 let artifact =
221 ContractArtifact::from_json(MULTI_FUNCTION_ARTIFACT).expect("parse artifact");
222
223 let balance = artifact
224 .find_function_by_type("balance_of", &FunctionType::Utility)
225 .expect("find balance_of as utility");
226 assert_eq!(balance.name, "balance_of");
227
228 let wrong_type = artifact.find_function_by_type("balance_of", &FunctionType::Public);
229 assert!(wrong_type.is_err());
230 }
231
232 #[test]
233 fn abi_value_field_roundtrip() {
234 let value = AbiValue::Field(Fr::from(1u64));
235 let json = serde_json::to_string(&value).expect("serialize AbiValue::Field");
236 assert!(json.contains("field"));
237 let decoded: AbiValue = serde_json::from_str(&json).expect("deserialize AbiValue");
238 assert_eq!(decoded, value);
239 }
240
241 #[test]
242 fn abi_value_boolean_roundtrip() {
243 let value = AbiValue::Boolean(true);
244 let json = serde_json::to_string(&value).expect("serialize");
245 let decoded: AbiValue = serde_json::from_str(&json).expect("deserialize");
246 assert_eq!(decoded, value);
247 }
248
249 #[test]
250 fn abi_value_integer_roundtrip() {
251 let value = AbiValue::Integer(42);
252 let json = serde_json::to_string(&value).expect("serialize");
253 let decoded: AbiValue = serde_json::from_str(&json).expect("deserialize");
254 assert_eq!(decoded, value);
255 }
256
257 #[test]
258 fn abi_value_array_roundtrip() {
259 let value = AbiValue::Array(vec![
260 AbiValue::Field(Fr::from(1u64)),
261 AbiValue::Field(Fr::from(2u64)),
262 ]);
263 let json = serde_json::to_string(&value).expect("serialize");
264 let decoded: AbiValue = serde_json::from_str(&json).expect("deserialize");
265 assert_eq!(decoded, value);
266 }
267
268 #[test]
269 fn abi_value_struct_roundtrip() {
270 let mut fields = BTreeMap::new();
271 fields.insert("x".to_owned(), AbiValue::Field(Fr::from(1u64)));
272 fields.insert("y".to_owned(), AbiValue::Integer(2));
273 let value = AbiValue::Struct(fields);
274 let json = serde_json::to_string(&value).expect("serialize");
275 let decoded: AbiValue = serde_json::from_str(&json).expect("deserialize");
276 assert_eq!(decoded, value);
277 }
278
279 #[test]
280 fn abi_type_struct_roundtrip() {
281 let typ = AbiType::Struct {
282 name: "Point".to_owned(),
283 fields: vec![
284 AbiParameter {
285 name: "x".to_owned(),
286 typ: AbiType::Field,
287 visibility: None,
288 },
289 AbiParameter {
290 name: "y".to_owned(),
291 typ: AbiType::Field,
292 visibility: None,
293 },
294 ],
295 };
296 let json = serde_json::to_string(&typ).expect("serialize AbiType::Struct");
297 let decoded: AbiType = serde_json::from_str(&json).expect("deserialize AbiType::Struct");
298 assert_eq!(decoded, typ);
299 }
300
301 #[test]
302 fn abi_type_array_roundtrip() {
303 let typ = AbiType::Array {
304 element: Box::new(AbiType::Field),
305 length: 10,
306 };
307 let json = serde_json::to_string(&typ).expect("serialize");
308 let decoded: AbiType = serde_json::from_str(&json).expect("deserialize");
309 assert_eq!(decoded, typ);
310 }
311
312 #[test]
313 fn artifact_from_invalid_json_fails() {
314 let result = ContractArtifact::from_json("not json");
315 assert!(result.is_err());
316 }
317
318 #[test]
319 fn from_signature_is_deterministic() {
320 let a = FunctionSelector::from_signature("sponsor_unconditionally()");
321 let b = FunctionSelector::from_signature("sponsor_unconditionally()");
322 assert_eq!(a, b);
323 }
324
325 #[test]
326 fn from_signature_different_inputs_differ() {
327 let a = FunctionSelector::from_signature("sponsor_unconditionally()");
328 let b = FunctionSelector::from_signature("claim_and_end_setup((Field),u128,Field,Field)");
329 assert_ne!(a, b);
330 }
331
332 #[test]
333 fn from_signature_empty_string() {
334 let a = FunctionSelector::from_signature("");
335 let b = FunctionSelector::from_signature("");
336 assert_eq!(a, b);
337 }
338
339 #[test]
340 fn from_signature_produces_4_bytes() {
341 let selector = FunctionSelector::from_signature("transfer(Field,Field,u64)");
342 assert_eq!(selector.0.len(), 4);
343 }
344
345 #[test]
346 fn function_selector_roundtrips_through_field() {
347 let selector = FunctionSelector::from_signature("set_authorized(Field,bool)");
348 assert_eq!(FunctionSelector::from_field(selector.to_field()), selector);
349 }
350
351 #[test]
352 fn authorization_selector_roundtrips_through_field() {
353 let selector =
354 AuthorizationSelector::from_signature("CallAuthorization((Field),(u32),Field)");
355 assert_eq!(
356 AuthorizationSelector::from_field(selector.to_field()),
357 selector
358 );
359 }
360
361 #[test]
364 fn type_checker_aztec_address() {
365 let typ = AbiType::Struct {
366 name: "aztec::protocol_types::address::AztecAddress".to_owned(),
367 fields: vec![AbiParameter {
368 name: "inner".to_owned(),
369 typ: AbiType::Field,
370 visibility: None,
371 }],
372 };
373 assert!(is_aztec_address_struct(&typ));
374 assert!(is_address_struct(&typ));
375 assert!(!is_eth_address_struct(&typ));
376 }
377
378 #[test]
379 fn type_checker_eth_address() {
380 let typ = AbiType::Struct {
381 name: "protocol_types::address::EthAddress".to_owned(),
382 fields: vec![AbiParameter {
383 name: "inner".to_owned(),
384 typ: AbiType::Field,
385 visibility: None,
386 }],
387 };
388 assert!(is_eth_address_struct(&typ));
389 assert!(is_address_struct(&typ));
390 assert!(!is_aztec_address_struct(&typ));
391 }
392
393 #[test]
394 fn type_checker_function_selector() {
395 let typ = AbiType::Struct {
396 name: "types::abis::function_selector::FunctionSelector".to_owned(),
397 fields: vec![AbiParameter {
398 name: "inner".to_owned(),
399 typ: AbiType::Field,
400 visibility: None,
401 }],
402 };
403 assert!(is_function_selector_struct(&typ));
404 }
405
406 #[test]
407 fn type_checker_wrapped_field() {
408 let yes = AbiType::Struct {
409 name: "SomeWrapped".to_owned(),
410 fields: vec![AbiParameter {
411 name: "inner".to_owned(),
412 typ: AbiType::Field,
413 visibility: None,
414 }],
415 };
416 assert!(is_wrapped_field_struct(&yes));
417
418 let no = AbiType::Struct {
419 name: "NotWrapped".to_owned(),
420 fields: vec![AbiParameter {
421 name: "value".to_owned(),
422 typ: AbiType::Field,
423 visibility: None,
424 }],
425 };
426 assert!(!is_wrapped_field_struct(&no));
427 }
428
429 #[test]
430 fn type_checker_bounded_vec() {
431 let typ = AbiType::Struct {
432 name: "std::collections::bounded_vec::BoundedVec".to_owned(),
433 fields: vec![
434 AbiParameter {
435 name: "storage".to_owned(),
436 typ: AbiType::Array {
437 element: Box::new(AbiType::Field),
438 length: 10,
439 },
440 visibility: None,
441 },
442 AbiParameter {
443 name: "len".to_owned(),
444 typ: AbiType::Integer {
445 sign: "unsigned".to_owned(),
446 width: 64,
447 },
448 visibility: None,
449 },
450 ],
451 };
452 assert!(is_bounded_vec_struct(&typ));
453 }
454
455 #[test]
456 fn type_checker_option() {
457 let typ = AbiType::Struct {
458 name: "std::option::Option".to_owned(),
459 fields: vec![
460 AbiParameter {
461 name: "_is_some".to_owned(),
462 typ: AbiType::Boolean,
463 visibility: None,
464 },
465 AbiParameter {
466 name: "_value".to_owned(),
467 typ: AbiType::Field,
468 visibility: None,
469 },
470 ],
471 };
472 assert!(is_option_struct(&typ));
473 }
474
475 #[test]
476 fn type_checker_non_matching() {
477 let typ = AbiType::Field;
478 assert!(!is_address_struct(&typ));
479 assert!(!is_function_selector_struct(&typ));
480 assert!(!is_wrapped_field_struct(&typ));
481 assert!(!is_bounded_vec_struct(&typ));
482 assert!(!is_option_struct(&typ));
483 assert!(!is_public_keys_struct(&typ));
484 }
485
486 #[test]
489 fn type_size_scalars() {
490 assert_eq!(abi_type_size(&AbiType::Field), 1);
491 assert_eq!(abi_type_size(&AbiType::Boolean), 1);
492 assert_eq!(
493 abi_type_size(&AbiType::Integer {
494 sign: "unsigned".to_owned(),
495 width: 64
496 }),
497 1
498 );
499 }
500
501 #[test]
502 fn type_size_string() {
503 assert_eq!(abi_type_size(&AbiType::String { length: 31 }), 31);
504 }
505
506 #[test]
507 fn type_size_array() {
508 assert_eq!(
509 abi_type_size(&AbiType::Array {
510 element: Box::new(AbiType::Field),
511 length: 5
512 }),
513 5
514 );
515 }
516
517 #[test]
518 fn type_size_nested_struct() {
519 let typ = AbiType::Struct {
520 name: "Point".to_owned(),
521 fields: vec![
522 AbiParameter {
523 name: "x".to_owned(),
524 typ: AbiType::Field,
525 visibility: None,
526 },
527 AbiParameter {
528 name: "y".to_owned(),
529 typ: AbiType::Field,
530 visibility: None,
531 },
532 ],
533 };
534 assert_eq!(abi_type_size(&typ), 2);
535 }
536
537 #[test]
538 fn count_arguments_size_works() {
539 let func = FunctionArtifact {
540 name: "test".to_owned(),
541 function_type: FunctionType::Public,
542 is_initializer: false,
543 is_static: false,
544 is_only_self: None,
545 parameters: vec![
546 AbiParameter {
547 name: "a".to_owned(),
548 typ: AbiType::Field,
549 visibility: None,
550 },
551 AbiParameter {
552 name: "b".to_owned(),
553 typ: AbiType::Array {
554 element: Box::new(AbiType::Field),
555 length: 3,
556 },
557 visibility: None,
558 },
559 ],
560 return_types: vec![],
561 error_types: None,
562 selector: None,
563 bytecode: None,
564 verification_key_hash: None,
565 verification_key: None,
566 custom_attributes: None,
567 is_unconstrained: None,
568 debug_symbols: None,
569 };
570 assert_eq!(count_arguments_size(&func), 4);
571 }
572
573 #[test]
576 fn encode_aztec_address_as_field() {
577 let typ = AbiType::Struct {
578 name: "aztec::protocol_types::address::AztecAddress".to_owned(),
579 fields: vec![AbiParameter {
580 name: "inner".to_owned(),
581 typ: AbiType::Field,
582 visibility: None,
583 }],
584 };
585 let value = AbiValue::Field(Fr::from(42u64));
586 let mut out = Vec::new();
587 encode_value(&typ, &value, &mut out).expect("encode address");
588 assert_eq!(out, vec![Fr::from(42u64)]);
589 }
590
591 #[test]
592 fn encode_bounded_vec() {
593 let typ = AbiType::Struct {
594 name: "std::collections::bounded_vec::BoundedVec".to_owned(),
595 fields: vec![
596 AbiParameter {
597 name: "storage".to_owned(),
598 typ: AbiType::Array {
599 element: Box::new(AbiType::Field),
600 length: 5,
601 },
602 visibility: None,
603 },
604 AbiParameter {
605 name: "len".to_owned(),
606 typ: AbiType::Integer {
607 sign: "unsigned".to_owned(),
608 width: 64,
609 },
610 visibility: None,
611 },
612 ],
613 };
614 let value = AbiValue::Array(vec![
615 AbiValue::Field(Fr::from(1u64)),
616 AbiValue::Field(Fr::from(2u64)),
617 AbiValue::Field(Fr::from(3u64)),
618 ]);
619 let mut out = Vec::new();
620 encode_value(&typ, &value, &mut out).expect("encode bounded vec");
621 assert_eq!(out.len(), 6);
622 assert_eq!(out[0], Fr::from(1u64));
623 assert_eq!(out[1], Fr::from(2u64));
624 assert_eq!(out[2], Fr::from(3u64));
625 assert_eq!(out[3], Fr::zero());
626 assert_eq!(out[4], Fr::zero());
627 assert_eq!(out[5], Fr::from(3u64));
628 }
629
630 #[test]
631 fn encode_option_some() {
632 let typ = AbiType::Struct {
633 name: "std::option::Option".to_owned(),
634 fields: vec![
635 AbiParameter {
636 name: "_is_some".to_owned(),
637 typ: AbiType::Boolean,
638 visibility: None,
639 },
640 AbiParameter {
641 name: "_value".to_owned(),
642 typ: AbiType::Field,
643 visibility: None,
644 },
645 ],
646 };
647 let value = AbiValue::Struct({
648 let mut m = BTreeMap::new();
649 m.insert("_is_some".to_owned(), AbiValue::Boolean(true));
650 m.insert("_value".to_owned(), AbiValue::Field(Fr::from(99u64)));
651 m
652 });
653 let mut out = Vec::new();
654 encode_value(&typ, &value, &mut out).expect("encode option some");
655 assert_eq!(out.len(), 2);
656 assert_eq!(out[0], Fr::one());
657 assert_eq!(out[1], Fr::from(99u64));
658 }
659
660 #[test]
661 fn encode_option_none() {
662 let typ = AbiType::Struct {
663 name: "std::option::Option".to_owned(),
664 fields: vec![
665 AbiParameter {
666 name: "_is_some".to_owned(),
667 typ: AbiType::Boolean,
668 visibility: None,
669 },
670 AbiParameter {
671 name: "_value".to_owned(),
672 typ: AbiType::Field,
673 visibility: None,
674 },
675 ],
676 };
677 let value = AbiValue::Struct({
678 let mut m = BTreeMap::new();
679 m.insert("_is_some".to_owned(), AbiValue::Boolean(false));
680 m.insert("_value".to_owned(), AbiValue::Field(Fr::zero()));
681 m
682 });
683 let mut out = Vec::new();
684 encode_value(&typ, &value, &mut out).expect("encode option none");
685 assert_eq!(out.len(), 2);
686 assert_eq!(out[0], Fr::zero());
687 assert_eq!(out[1], Fr::zero());
688 }
689
690 #[test]
691 fn encode_signed_negative_integer() {
692 let typ = AbiType::Integer {
693 sign: "signed".to_owned(),
694 width: 8,
695 };
696 let value = AbiValue::Integer(-1);
697 let mut out = Vec::new();
698 encode_value(&typ, &value, &mut out).expect("encode signed int");
699 assert_eq!(out.len(), 1);
700 let bytes = out[0].to_be_bytes();
701 let raw = u128::from_be_bytes(bytes[16..].try_into().unwrap());
702 assert_eq!(raw, 255);
703 }
704
705 #[test]
706 fn encode_signed_positive_integer() {
707 let typ = AbiType::Integer {
708 sign: "signed".to_owned(),
709 width: 8,
710 };
711 let value = AbiValue::Integer(42);
712 let mut out = Vec::new();
713 encode_value(&typ, &value, &mut out).expect("encode signed int");
714 let bytes = out[0].to_be_bytes();
715 let raw = u128::from_be_bytes(bytes[16..].try_into().unwrap());
716 assert_eq!(raw, 42);
717 }
718
719 #[test]
722 fn decode_single_field() {
723 let fields = vec![Fr::from(42u64)];
724 let result = decode_from_abi(&[AbiType::Field], &fields).expect("decode");
725 assert_eq!(result, AbiDecoded::Field(Fr::from(42u64)));
726 }
727
728 #[test]
729 fn decode_boolean() {
730 let fields = vec![Fr::one()];
731 let result = decode_from_abi(&[AbiType::Boolean], &fields).expect("decode");
732 assert_eq!(result, AbiDecoded::Boolean(true));
733
734 let fields = vec![Fr::zero()];
735 let result = decode_from_abi(&[AbiType::Boolean], &fields).expect("decode");
736 assert_eq!(result, AbiDecoded::Boolean(false));
737 }
738
739 #[test]
740 fn decode_unsigned_integer() {
741 let typ = AbiType::Integer {
742 sign: "unsigned".to_owned(),
743 width: 64,
744 };
745 let mut encoded = Vec::new();
746 encode_value(&typ, &AbiValue::Integer(42), &mut encoded).expect("encode");
747 let result = decode_from_abi(&[typ], &encoded).expect("decode");
748 assert_eq!(result, AbiDecoded::Integer(42));
749 }
750
751 #[test]
752 fn decode_signed_negative_integer() {
753 let typ = AbiType::Integer {
754 sign: "signed".to_owned(),
755 width: 32,
756 };
757 let mut encoded = Vec::new();
758 encode_value(&typ, &AbiValue::Integer(-100), &mut encoded).expect("encode");
759 let result = decode_from_abi(&[typ], &encoded).expect("decode");
760 assert_eq!(result, AbiDecoded::Integer(-100));
761 }
762
763 #[test]
764 fn decode_array() {
765 let typ = AbiType::Array {
766 element: Box::new(AbiType::Field),
767 length: 3,
768 };
769 let fields = vec![Fr::from(1u64), Fr::from(2u64), Fr::from(3u64)];
770 let result = decode_from_abi(&[typ], &fields).expect("decode");
771 assert_eq!(
772 result,
773 AbiDecoded::Array(vec![
774 AbiDecoded::Field(Fr::from(1u64)),
775 AbiDecoded::Field(Fr::from(2u64)),
776 AbiDecoded::Field(Fr::from(3u64)),
777 ])
778 );
779 }
780
781 #[test]
782 fn decode_struct() {
783 let typ = AbiType::Struct {
784 name: "Point".to_owned(),
785 fields: vec![
786 AbiParameter {
787 name: "x".to_owned(),
788 typ: AbiType::Field,
789 visibility: None,
790 },
791 AbiParameter {
792 name: "y".to_owned(),
793 typ: AbiType::Field,
794 visibility: None,
795 },
796 ],
797 };
798 let fields = vec![Fr::from(10u64), Fr::from(20u64)];
799 let result = decode_from_abi(&[typ], &fields).expect("decode");
800 let mut expected = BTreeMap::new();
801 expected.insert("x".to_owned(), AbiDecoded::Field(Fr::from(10u64)));
802 expected.insert("y".to_owned(), AbiDecoded::Field(Fr::from(20u64)));
803 assert_eq!(result, AbiDecoded::Struct(expected));
804 }
805
806 #[test]
807 fn decode_aztec_address() {
808 let typ = AbiType::Struct {
809 name: "aztec::protocol_types::address::AztecAddress".to_owned(),
810 fields: vec![AbiParameter {
811 name: "inner".to_owned(),
812 typ: AbiType::Field,
813 visibility: None,
814 }],
815 };
816 let fields = vec![Fr::from(42u64)];
817 let result = decode_from_abi(&[typ], &fields).expect("decode");
818 assert_eq!(
819 result,
820 AbiDecoded::Address(crate::types::AztecAddress(Fr::from(42u64)))
821 );
822 }
823
824 #[test]
825 fn decode_option_some() {
826 let typ = AbiType::Struct {
827 name: "std::option::Option".to_owned(),
828 fields: vec![
829 AbiParameter {
830 name: "_is_some".to_owned(),
831 typ: AbiType::Boolean,
832 visibility: None,
833 },
834 AbiParameter {
835 name: "_value".to_owned(),
836 typ: AbiType::Field,
837 visibility: None,
838 },
839 ],
840 };
841 let fields = vec![Fr::one(), Fr::from(99u64)];
842 let result = decode_from_abi(&[typ], &fields).expect("decode");
843 assert_eq!(result, AbiDecoded::Field(Fr::from(99u64)));
844 }
845
846 #[test]
847 fn decode_option_none() {
848 let typ = AbiType::Struct {
849 name: "std::option::Option".to_owned(),
850 fields: vec![
851 AbiParameter {
852 name: "_is_some".to_owned(),
853 typ: AbiType::Boolean,
854 visibility: None,
855 },
856 AbiParameter {
857 name: "_value".to_owned(),
858 typ: AbiType::Field,
859 visibility: None,
860 },
861 ],
862 };
863 let fields = vec![Fr::zero(), Fr::zero()];
864 let result = decode_from_abi(&[typ], &fields).expect("decode");
865 assert_eq!(result, AbiDecoded::None);
866 }
867
868 #[test]
869 fn decode_string() {
870 let typ = AbiType::String { length: 5 };
871 let fields = vec![
872 Fr::from(b'H' as u64),
873 Fr::from(b'e' as u64),
874 Fr::from(b'l' as u64),
875 Fr::from(b'l' as u64),
876 Fr::from(b'o' as u64),
877 ];
878 let result = decode_from_abi(&[typ], &fields).expect("decode");
879 assert_eq!(result, AbiDecoded::String("Hello".to_owned()));
880 }
881
882 #[test]
883 fn decode_insufficient_fields_errors() {
884 let typ = AbiType::Array {
885 element: Box::new(AbiType::Field),
886 length: 5,
887 };
888 let fields = vec![Fr::from(1u64), Fr::from(2u64)];
889 let result = decode_from_abi(&[typ], &fields);
890 assert!(result.is_err());
891 }
892
893 #[test]
894 fn encode_decode_roundtrip_complex() {
895 let bv_typ = AbiType::Struct {
896 name: "std::collections::bounded_vec::BoundedVec".to_owned(),
897 fields: vec![
898 AbiParameter {
899 name: "storage".to_owned(),
900 typ: AbiType::Array {
901 element: Box::new(AbiType::Field),
902 length: 5,
903 },
904 visibility: None,
905 },
906 AbiParameter {
907 name: "len".to_owned(),
908 typ: AbiType::Integer {
909 sign: "unsigned".to_owned(),
910 width: 64,
911 },
912 visibility: None,
913 },
914 ],
915 };
916 let value = AbiValue::Array(vec![
917 AbiValue::Field(Fr::from(10u64)),
918 AbiValue::Field(Fr::from(20u64)),
919 AbiValue::Field(Fr::from(30u64)),
920 ]);
921 let mut encoded = Vec::new();
922 encode_value(&bv_typ, &value, &mut encoded).expect("encode");
923 let decoded = decode_from_abi(&[bv_typ], &encoded).expect("decode");
924 assert_eq!(
925 decoded,
926 AbiDecoded::Array(vec![
927 AbiDecoded::Field(Fr::from(10u64)),
928 AbiDecoded::Field(Fr::from(20u64)),
929 AbiDecoded::Field(Fr::from(30u64)),
930 ])
931 );
932 }
933
934 #[test]
937 fn note_selector_valid() {
938 let ns = NoteSelector::new(0).expect("valid");
939 assert_eq!(ns.0, 0);
940 let ns = NoteSelector::new(127).expect("valid");
941 assert_eq!(ns.0, 127);
942 }
943
944 #[test]
945 fn note_selector_rejects_128() {
946 assert!(NoteSelector::new(128).is_err());
947 assert!(NoteSelector::new(255).is_err());
948 }
949
950 #[test]
951 fn note_selector_field_roundtrip() {
952 let ns = NoteSelector::new(42).expect("valid");
953 let field = ns.to_field();
954 let ns2 = NoteSelector::from_field(field).expect("from_field");
955 assert_eq!(ns, ns2);
956 }
957
958 #[test]
959 fn note_selector_hex_roundtrip() {
960 let ns = NoteSelector::from_hex("0x1a").expect("valid");
961 assert_eq!(ns.0, 0x1a);
962 assert_eq!(ns.to_string(), "0x1a");
963 }
964
965 #[test]
966 fn note_selector_serde_roundtrip() {
967 let ns = NoteSelector::new(42).expect("valid");
968 let json = serde_json::to_string(&ns).expect("serialize");
969 assert_eq!(json, "42");
970 let decoded: NoteSelector = serde_json::from_str(&json).expect("deserialize");
971 assert_eq!(decoded, ns);
972 }
973
974 #[test]
975 fn note_selector_serde_rejects_invalid() {
976 let result: Result<NoteSelector, _> = serde_json::from_str("200");
977 assert!(result.is_err());
978 }
979
980 #[test]
983 fn artifact_to_buffer_from_buffer_roundtrip() {
984 let artifact = ContractArtifact::from_json(MINIMAL_ARTIFACT).expect("parse artifact");
985 let buffer = artifact.to_buffer().expect("to_buffer");
986 let decoded = ContractArtifact::from_buffer(&buffer).expect("from_buffer");
987 assert_eq!(decoded, artifact);
988 }
989
990 #[test]
991 fn artifact_to_json_from_json_roundtrip() {
992 let artifact = ContractArtifact::from_json(MINIMAL_ARTIFACT).expect("parse artifact");
993 let json = artifact.to_json().expect("to_json");
994 let decoded = ContractArtifact::from_json(&json).expect("from_json");
995 assert_eq!(decoded, artifact);
996 }
997
998 #[test]
999 fn artifact_from_buffer_rejects_invalid() {
1000 let result = ContractArtifact::from_buffer(b"not json");
1001 assert!(result.is_err());
1002 }
1003
1004 #[test]
1007 fn buffer_fields_roundtrip() {
1008 let data = b"Hello, Aztec! This is a test of buffer encoding.";
1009 let fields = buffer_as_fields(data, 100).expect("encode");
1010 let decoded = buffer_from_fields(&fields).expect("decode");
1011 assert_eq!(decoded, data);
1012 }
1013
1014 #[test]
1015 fn buffer_fields_empty() {
1016 let fields = buffer_as_fields(&[], 10).expect("encode");
1017 assert_eq!(fields.len(), 10);
1018 assert_eq!(fields[0], Fr::from(0u64));
1019 let decoded = buffer_from_fields(&fields).expect("decode");
1020 assert!(decoded.is_empty());
1021 }
1022
1023 #[test]
1024 fn buffer_fields_exactly_31_bytes() {
1025 let data = [0xABu8; 31];
1026 let fields = buffer_as_fields(&data, 10).expect("encode");
1027 assert_eq!(fields[0], Fr::from(31u64));
1028 let decoded = buffer_from_fields(&fields).expect("decode");
1029 assert_eq!(decoded, data);
1030 }
1031
1032 #[test]
1033 fn buffer_fields_62_bytes() {
1034 let data = [0xFFu8; 62];
1035 let fields = buffer_as_fields(&data, 10).expect("encode");
1036 assert_eq!(fields[0], Fr::from(62u64));
1037 let decoded = buffer_from_fields(&fields).expect("decode");
1038 assert_eq!(decoded, data);
1039 }
1040
1041 #[test]
1042 fn buffer_fields_exceeds_max() {
1043 let data = [0u8; 100];
1044 let result = buffer_as_fields(&data, 3);
1045 assert!(result.is_err());
1046 }
1047
1048 #[test]
1049 fn buffer_from_fields_empty_errors() {
1050 let result = buffer_from_fields(&[]);
1051 assert!(result.is_err());
1052 }
1053}