1use alloc::{borrow::Cow, string::String, vec::Vec};
2use core::fmt;
3use core::ops::Deref;
4use serde::{Deserialize, Serialize};
5use sha2::{
6 digest::{Digest, Update},
7 Sha256,
8};
9
10use crate::Binary;
11use crate::{HexBinary, __internal::forward_ref_partial_eq};
12
13#[derive(
30 Serialize,
31 Deserialize,
32 Clone,
33 Debug,
34 PartialEq,
35 Eq,
36 PartialOrd,
37 Ord,
38 Hash,
39 schemars::JsonSchema,
40 cw_schema::Schemaifier,
41)]
42#[schemaifier(type = cw_schema::NodeType::Address)]
43pub struct Addr(String);
44
45forward_ref_partial_eq!(Addr, Addr);
46
47impl Addr {
48 pub fn unchecked(input: impl Into<String>) -> Addr {
64 Addr(input.into())
65 }
66
67 #[inline]
68 pub fn as_str(&self) -> &str {
69 self.0.as_str()
70 }
71
72 #[inline]
76 pub fn as_bytes(&self) -> &[u8] {
77 self.0.as_bytes()
78 }
79
80 #[inline]
82 pub fn into_string(self) -> String {
83 self.0
84 }
85}
86
87impl fmt::Display for Addr {
88 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89 write!(f, "{}", &self.0)
90 }
91}
92
93impl AsRef<str> for Addr {
94 #[inline]
95 fn as_ref(&self) -> &str {
96 self.as_str()
97 }
98}
99
100impl From<Addr> for String {
104 fn from(addr: Addr) -> Self {
105 addr.0
106 }
107}
108
109impl From<&Addr> for String {
110 fn from(addr: &Addr) -> Self {
111 addr.0.clone()
112 }
113}
114
115impl From<Addr> for Cow<'_, Addr> {
116 fn from(addr: Addr) -> Self {
117 Cow::Owned(addr)
118 }
119}
120
121impl<'a> From<&'a Addr> for Cow<'a, Addr> {
122 fn from(addr: &'a Addr) -> Self {
123 Cow::Borrowed(addr)
124 }
125}
126
127#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, Hash, schemars::JsonSchema)]
143pub struct CanonicalAddr(Binary);
144
145impl PartialEq<Binary> for CanonicalAddr {
147 fn eq(&self, rhs: &Binary) -> bool {
148 &self.0 == rhs
149 }
150}
151
152impl PartialEq<CanonicalAddr> for Binary {
154 fn eq(&self, rhs: &CanonicalAddr) -> bool {
155 self == &rhs.0
156 }
157}
158
159impl PartialEq<HexBinary> for CanonicalAddr {
161 fn eq(&self, rhs: &HexBinary) -> bool {
162 self.as_slice() == rhs.as_slice()
163 }
164}
165
166impl PartialEq<CanonicalAddr> for HexBinary {
168 fn eq(&self, rhs: &CanonicalAddr) -> bool {
169 self.as_slice() == rhs.0.as_slice()
170 }
171}
172
173impl From<&[u8]> for CanonicalAddr {
174 fn from(source: &[u8]) -> Self {
175 Self(source.into())
176 }
177}
178
179impl<const LENGTH: usize> From<&[u8; LENGTH]> for CanonicalAddr {
181 fn from(source: &[u8; LENGTH]) -> Self {
182 Self(source.into())
183 }
184}
185
186impl<const LENGTH: usize> From<[u8; LENGTH]> for CanonicalAddr {
188 fn from(source: [u8; LENGTH]) -> Self {
189 Self(source.into())
190 }
191}
192
193impl From<Vec<u8>> for CanonicalAddr {
195 fn from(source: Vec<u8>) -> Self {
196 Self(source.into())
197 }
198}
199
200impl From<CanonicalAddr> for Vec<u8> {
202 fn from(source: CanonicalAddr) -> Vec<u8> {
203 source.0.into()
204 }
205}
206
207impl From<Binary> for CanonicalAddr {
209 fn from(source: Binary) -> Self {
210 Self(source)
211 }
212}
213
214impl From<CanonicalAddr> for Binary {
216 fn from(source: CanonicalAddr) -> Binary {
217 source.0
218 }
219}
220
221impl From<HexBinary> for CanonicalAddr {
223 fn from(source: HexBinary) -> Self {
224 Self(source.into())
225 }
226}
227
228impl From<CanonicalAddr> for HexBinary {
230 fn from(source: CanonicalAddr) -> HexBinary {
231 source.0.into()
232 }
233}
234
235impl Deref for CanonicalAddr {
241 type Target = [u8];
242
243 fn deref(&self) -> &Self::Target {
244 self.as_slice()
245 }
246}
247
248impl CanonicalAddr {
249 pub fn as_slice(&self) -> &[u8] {
250 self.0.as_slice()
251 }
252}
253
254impl fmt::Display for CanonicalAddr {
255 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256 for byte in self.0.as_slice() {
257 write!(f, "{byte:02X}")?;
258 }
259 Ok(())
260 }
261}
262
263#[derive(Debug, PartialEq, Eq, thiserror::Error)]
264pub enum Instantiate2AddressError {
265 InvalidChecksumLength,
267 InvalidSaltLength,
269}
270
271impl fmt::Display for Instantiate2AddressError {
272 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
273 match self {
274 Instantiate2AddressError::InvalidChecksumLength => write!(f, "invalid checksum length"),
275 Instantiate2AddressError::InvalidSaltLength => write!(f, "invalid salt length"),
276 }
277 }
278}
279
280pub fn instantiate2_address(
319 checksum: &[u8],
320 creator: &CanonicalAddr,
321 salt: &[u8],
322) -> Result<CanonicalAddr, Instantiate2AddressError> {
323 let msg = b"";
326 let len = 32;
327 instantiate2_address_impl(checksum, creator, salt, msg, len)
328}
329
330#[doc(hidden)]
363#[inline] pub fn instantiate2_address_impl(
365 checksum: &[u8],
366 creator: &CanonicalAddr,
367 salt: &[u8],
368 msg: &[u8],
369 len: usize,
370) -> Result<CanonicalAddr, Instantiate2AddressError> {
371 if checksum.len() != 32 {
372 return Err(Instantiate2AddressError::InvalidChecksumLength);
373 }
374
375 if salt.is_empty() || salt.len() > 64 {
376 return Err(Instantiate2AddressError::InvalidSaltLength);
377 };
378
379 let mut key = Vec::<u8>::new();
380 key.extend_from_slice(b"wasm\0");
381 key.extend_from_slice(&(checksum.len() as u64).to_be_bytes());
382 key.extend_from_slice(checksum);
383 key.extend_from_slice(&(creator.len() as u64).to_be_bytes());
384 key.extend_from_slice(creator);
385 key.extend_from_slice(&(salt.len() as u64).to_be_bytes());
386 key.extend_from_slice(salt);
387 key.extend_from_slice(&(msg.len() as u64).to_be_bytes());
388 key.extend_from_slice(msg);
389 let mut address_data = hash("module", &key);
390
391 if len != 32 {
395 debug_assert!(len <= 32);
396 debug_assert!(len > 0);
397 address_data.truncate(len);
398 }
399
400 Ok(address_data.into())
401}
402
403fn hash(ty: &str, key: &[u8]) -> Vec<u8> {
406 let inner = Sha256::digest(ty.as_bytes());
407 Sha256::new().chain(inner).chain(key).finalize().to_vec()
408}
409
410#[cfg(test)]
411mod tests {
412 use super::*;
413 use crate::assert_hash_works;
414 use crate::HexBinary;
415
416 use hex_literal::hex;
417
418 #[test]
419 fn addr_unchecked_works() {
420 let a = Addr::unchecked("123");
421 let aa = Addr::unchecked(String::from("123"));
422 let b = Addr::unchecked("be");
423 assert_eq!(a, aa);
424 assert_ne!(a, b);
425 }
426
427 #[test]
428 fn addr_as_str_works() {
429 let addr = Addr::unchecked("literal-string");
430 assert_eq!(addr.as_str(), "literal-string");
431 }
432
433 #[test]
434 fn addr_as_bytes_works() {
435 let addr = Addr::unchecked("literal-string");
436 assert_eq!(
437 addr.as_bytes(),
438 [108, 105, 116, 101, 114, 97, 108, 45, 115, 116, 114, 105, 110, 103]
439 );
440 }
441
442 #[test]
443 fn addr_implements_display() {
444 let addr = Addr::unchecked("cos934gh9034hg04g0h134");
445 let embedded = format!("Address: {addr}");
446 assert_eq!(embedded, "Address: cos934gh9034hg04g0h134");
447 assert_eq!(addr.to_string(), "cos934gh9034hg04g0h134");
448 }
449
450 #[test]
451 fn addr_implements_as_ref_for_str() {
452 let addr = Addr::unchecked("literal-string");
453 assert_eq!(addr.as_ref(), "literal-string");
454 }
455
456 #[test]
457 fn addr_implements_partial_eq_addr_ref() {
458 let addr = Addr::unchecked("cos934gh9034hg04g0h134");
459 let addr_ref = &addr;
460 let addr_ref2 = &addr;
461
462 assert_eq!(addr, addr_ref);
464 assert_eq!(addr_ref, addr);
466 assert_eq!(addr_ref, addr_ref2);
468 }
469
470 #[test]
471 fn addr_implements_into_string() {
472 let addr = Addr::unchecked("cos934gh9034hg04g0h134");
474 let string: String = addr.into();
475 assert_eq!(string, "cos934gh9034hg04g0h134");
476
477 let addr = Addr::unchecked("cos934gh9034hg04g0h134");
479 let addr_ref = &addr;
480 let string: String = addr_ref.into();
481 assert_eq!(string, "cos934gh9034hg04g0h134");
482 }
483
484 #[test]
486 fn canonical_addr_from_slice() {
487 let bytes: &[u8] = &[0u8, 187, 61, 11, 250, 0];
489 let canonical_addr_slice = CanonicalAddr::from(bytes);
490 assert_eq!(canonical_addr_slice.as_slice(), &[0u8, 187, 61, 11, 250, 0]);
491
492 let bytes: Vec<u8> = vec![0u8, 187, 61, 11, 250, 0];
494 let canonical_addr_vec = CanonicalAddr::from(bytes);
495 assert_eq!(canonical_addr_vec.as_slice(), &[0u8, 187, 61, 11, 250, 0]);
496 }
497
498 #[test]
499 fn canonical_addr_implements_partial_eq_with_binary() {
500 let addr = CanonicalAddr::from([1, 2, 3]);
501 let bin1 = Binary::from([1, 2, 3]);
502 let bin2 = Binary::from([42, 43]);
503
504 assert_eq!(addr, bin1);
505 assert_eq!(bin1, addr);
506 assert_ne!(addr, bin2);
507 assert_ne!(bin2, addr);
508 }
509
510 #[test]
511 fn canonical_addr_implements_partial_eq_with_hex_binary() {
512 let addr = CanonicalAddr::from([1, 2, 3]);
513 let bin1 = HexBinary::from([1, 2, 3]);
514 let bin2 = HexBinary::from([42, 43]);
515
516 assert_eq!(addr, bin1);
517 assert_eq!(bin1, addr);
518 assert_ne!(addr, bin2);
519 assert_ne!(bin2, addr);
520 }
521
522 #[test]
523 fn canonical_addr_implements_from_array() {
524 let array = [1, 2, 3];
525 let addr = CanonicalAddr::from(array);
526 assert_eq!(addr.as_slice(), [1, 2, 3]);
527
528 let array_ref = b"foo";
529 let addr = CanonicalAddr::from(array_ref);
530 assert_eq!(addr.as_slice(), [0x66, 0x6f, 0x6f]);
531 }
532
533 #[test]
534 fn canonical_addr_implements_from_and_to_vector() {
535 let original = vec![0u8, 187, 61, 11, 250, 0];
538 let original_ptr = original.as_ptr();
539 let addr: CanonicalAddr = original.into();
540 assert_eq!(addr.as_slice(), [0u8, 187, 61, 11, 250, 0]);
541 assert_eq!(
542 (addr.0).as_slice().as_ptr(),
543 original_ptr,
544 "must not be copied"
545 );
546
547 let original = vec![0u8, 187, 61, 11, 250, 0];
549 let original_ptr = original.as_ptr();
550 let addr = CanonicalAddr::from(original);
551 assert_eq!(addr.as_slice(), [0u8, 187, 61, 11, 250, 0]);
552 assert_eq!(
553 (addr.0).as_slice().as_ptr(),
554 original_ptr,
555 "must not be copied"
556 );
557
558 let original = CanonicalAddr::from(vec![0u8, 187, 61, 11, 250, 0]);
561 let original_ptr = (original.0).as_slice().as_ptr();
562 let vec: Vec<u8> = original.into();
563 assert_eq!(vec.as_slice(), [0u8, 187, 61, 11, 250, 0]);
564 assert_eq!(vec.as_ptr(), original_ptr, "must not be copied");
565
566 let original = CanonicalAddr::from(vec![7u8, 35, 49, 101, 0, 255]);
568 let original_ptr = (original.0).as_slice().as_ptr();
569 let vec = Vec::<u8>::from(original);
570 assert_eq!(vec.as_slice(), [7u8, 35, 49, 101, 0, 255]);
571 assert_eq!(vec.as_ptr(), original_ptr, "must not be copied");
572 }
573
574 #[test]
575 fn canonical_addr_implements_from_and_to_binary() {
576 let original = Binary::from([0u8, 187, 61, 11, 250, 0]);
578 let original_ptr = original.as_ptr();
579 let addr = CanonicalAddr::from(original);
580 assert_eq!(addr.as_slice(), [0u8, 187, 61, 11, 250, 0]);
581 assert_eq!(
582 (addr.0).as_slice().as_ptr(),
583 original_ptr,
584 "must not be copied"
585 );
586
587 let original = CanonicalAddr::from(vec![7u8, 35, 49, 101, 0, 255]);
589 let original_ptr = (original.0).as_slice().as_ptr();
590 let bin = Binary::from(original);
591 assert_eq!(bin.as_slice(), [7u8, 35, 49, 101, 0, 255]);
592 assert_eq!(bin.as_ptr(), original_ptr, "must not be copied");
593 }
594
595 #[test]
596 fn canonical_addr_implements_from_and_to_hex_binary() {
597 let original = HexBinary::from([0u8, 187, 61, 11, 250, 0]);
599 let original_ptr = original.as_ptr();
600 let addr = CanonicalAddr::from(original);
601 assert_eq!(addr.as_slice(), [0u8, 187, 61, 11, 250, 0]);
602 assert_eq!(
603 (addr.0).as_slice().as_ptr(),
604 original_ptr,
605 "must not be copied"
606 );
607
608 let original = CanonicalAddr::from(vec![7u8, 35, 49, 101, 0, 255]);
610 let original_ptr = (original.0).as_slice().as_ptr();
611 let bin = HexBinary::from(original);
612 assert_eq!(bin.as_slice(), [7u8, 35, 49, 101, 0, 255]);
613 assert_eq!(bin.as_ptr(), original_ptr, "must not be copied");
614 }
615
616 #[test]
617 fn canonical_addr_len() {
618 let bytes: &[u8] = &[0u8, 187, 61, 11, 250, 0];
619 let canonical_addr = CanonicalAddr::from(bytes);
620 assert_eq!(canonical_addr.len(), bytes.len());
621 }
622
623 #[test]
624 fn canonical_addr_is_empty() {
625 let bytes: &[u8] = &[0u8, 187, 61, 11, 250, 0];
626 let canonical_addr = CanonicalAddr::from(bytes);
627 assert!(!canonical_addr.is_empty());
628 let empty_canonical_addr = CanonicalAddr::from(vec![]);
629 assert!(empty_canonical_addr.is_empty());
630 }
631
632 #[test]
633 fn canonical_addr_implements_display() {
634 let bytes: &[u8] = &[
635 0x12, 0x03, 0xab, 0x00, 0xff,
640 ];
641 let address = CanonicalAddr::from(bytes);
642 let embedded = format!("Address: {address}");
643 assert_eq!(embedded, "Address: 1203AB00FF");
644 assert_eq!(address.to_string(), "1203AB00FF");
645 }
646
647 #[test]
648 fn canonical_addr_implements_deref() {
649 let bytes: &[u8] = &[0u8, 187, 61, 11, 250, 0];
651 let canonical_addr = CanonicalAddr::from(bytes);
652 assert_eq!(*canonical_addr, [0u8, 187, 61, 11, 250, 0]);
653
654 let bytes: &[u8] = &[0u8, 187, 61, 11, 250, 0];
656 let canonical_addr = CanonicalAddr::from(bytes);
657 assert_eq!(canonical_addr.len(), 6);
658 let canonical_addr_slice: &[u8] = &canonical_addr;
659 assert_eq!(canonical_addr_slice, &[0u8, 187, 61, 11, 250, 0]);
660 }
661
662 #[test]
665 fn canonical_addr_implements_hash_eq() {
666 let alice = CanonicalAddr::from([0, 187, 61, 11, 250, 0]);
667 let bob = CanonicalAddr::from([16, 21, 33, 0, 255, 9]);
668 assert_hash_works!(alice, bob);
669 }
670
671 fn flexible<'a>(a: impl Into<Cow<'a, Addr>>) -> String {
673 a.into().into_owned().to_string()
674 }
675
676 #[test]
677 fn addr_into_cow() {
678 let value = "wasmeucn0ur0ncny2308ry";
680 let addr = Addr::unchecked(value);
681
682 assert_eq!(value, &flexible(&addr));
684 assert_eq!(value, &flexible(addr));
686 }
687
688 #[test]
689 fn instantiate2_address_impl_works() {
690 let checksum1 =
691 HexBinary::from_hex("13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5")
692 .unwrap();
693 let creator1 = CanonicalAddr::from(hex!("9999999999aaaaaaaaaabbbbbbbbbbcccccccccc"));
694 let salt1 = hex!("61");
695 let salt2 = hex!("aabbccddeeffffeeddbbccddaa66551155aaaabbcc787878789900aabbccddeeffffeeddbbccddaa66551155aaaabbcc787878789900aabbbbcc221100acadae");
696 let msg1: &[u8] = b"";
697 let msg2: &[u8] = b"{}";
698 let msg3: &[u8] = b"{\"some\":123,\"structure\":{\"nested\":[\"ok\",true]}}";
699
700 let expected = CanonicalAddr::from(hex!(
702 "5e865d3e45ad3e961f77fd77d46543417ced44d924dc3e079b5415ff6775f847"
703 ));
704 assert_eq!(
705 instantiate2_address_impl(&checksum1, &creator1, &salt1, msg1, 32).unwrap(),
706 expected
707 );
708
709 let expected = CanonicalAddr::from(hex!(
711 "0995499608947a5281e2c7ebd71bdb26a1ad981946dad57f6c4d3ee35de77835"
712 ));
713 assert_eq!(
714 instantiate2_address_impl(&checksum1, &creator1, &salt1, msg2, 32).unwrap(),
715 expected
716 );
717
718 let expected = CanonicalAddr::from(hex!(
720 "83326e554723b15bac664ceabc8a5887e27003abe9fbd992af8c7bcea4745167"
721 ));
722 assert_eq!(
723 instantiate2_address_impl(&checksum1, &creator1, &salt1, msg3, 32).unwrap(),
724 expected
725 );
726
727 let expected = CanonicalAddr::from(hex!(
729 "9384c6248c0bb171e306fd7da0993ec1e20eba006452a3a9e078883eb3594564"
730 ));
731 assert_eq!(
732 instantiate2_address_impl(&checksum1, &creator1, &salt2, b"", 32).unwrap(),
733 expected
734 );
735
736 let empty = Vec::<u8>::new();
738 assert!(matches!(
739 instantiate2_address_impl(&checksum1, &creator1, &empty, b"", 32).unwrap_err(),
740 Instantiate2AddressError::InvalidSaltLength
741 ));
742 let too_long = vec![0x11; 65];
743 assert!(matches!(
744 instantiate2_address_impl(&checksum1, &creator1, &too_long, b"", 32).unwrap_err(),
745 Instantiate2AddressError::InvalidSaltLength
746 ));
747
748 let broken_cs = hex!("13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2");
750 assert!(matches!(
751 instantiate2_address_impl(&broken_cs, &creator1, &salt1, b"", 32).unwrap_err(),
752 Instantiate2AddressError::InvalidChecksumLength
753 ));
754 let broken_cs = hex!("");
755 assert!(matches!(
756 instantiate2_address_impl(&broken_cs, &creator1, &salt1, b"", 32).unwrap_err(),
757 Instantiate2AddressError::InvalidChecksumLength
758 ));
759 let broken_cs = hex!("13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2aaaa");
760 assert!(matches!(
761 instantiate2_address_impl(&broken_cs, &creator1, &salt1, b"", 32).unwrap_err(),
762 Instantiate2AddressError::InvalidChecksumLength
763 ));
764 }
765
766 #[test]
767 fn instantiate2_address_impl_truncates_address_data_to_first_len_bytes() {
768 let checksum =
770 HexBinary::from_hex("13a1fc994cc6d1c81b746ee0c0ff6f90043875e0bf1d9be6b7d779fc978dc2a5")
771 .unwrap();
772 let creator = CanonicalAddr::from(hex!("9999999999aaaaaaaaaabbbbbbbbbbcccccccccc"));
773 let salt = hex!("61");
774
775 let data = [
776 (
777 32,
778 "5e865d3e45ad3e961f77fd77d46543417ced44d924dc3e079b5415ff6775f847",
779 ),
780 (
781 31,
782 "5e865d3e45ad3e961f77fd77d46543417ced44d924dc3e079b5415ff6775f8",
783 ),
784 (
785 30,
786 "5e865d3e45ad3e961f77fd77d46543417ced44d924dc3e079b5415ff6775",
787 ),
788 (21, "5e865d3e45ad3e961f77fd77d46543417ced44d924"),
789 (20, "5e865d3e45ad3e961f77fd77d46543417ced44d9"),
790 (19, "5e865d3e45ad3e961f77fd77d46543417ced44"),
791 (16, "5e865d3e45ad3e961f77fd77d4654341"),
792 (8, "5e865d3e45ad3e96"),
793 (1, "5e"),
794 ];
795
796 for (len, expected) in data {
797 let expected = CanonicalAddr::from(HexBinary::from_hex(expected).unwrap());
798 assert_eq!(
799 instantiate2_address_impl(&checksum, &creator, &salt, b"", len).unwrap(),
800 expected
801 );
802 }
803 }
804
805 #[test]
806 fn instantiate2_address_impl_matches_wasmd_for_len_24() {
807 let checksum =
814 HexBinary::from_hex("1122112211221122112211221122112211221122112211221122112211221122")
815 .unwrap();
816 let creator = CanonicalAddr::from(hex!("3333333333333333333333333333333333333333"));
817 let salt = hex!("aabbaabb");
818
819 let expected =
820 CanonicalAddr::from(hex!["da1aaec9d0ddc75b873079eb1b4f7ddd73a0e3170225fec4"]);
821 assert_eq!(
822 instantiate2_address_impl(&checksum, &creator, &salt, b"", 24).unwrap(),
823 expected
824 );
825 }
826
827 #[test]
828 fn instantiate2_address_impl_works_for_cosmjs_test_vectors() {
829 const COSMOS_ED25519_TESTS_JSON: &str = "./testdata/instantiate2_addresses.json";
831
832 #[derive(Deserialize, Debug)]
833 #[serde(rename_all = "camelCase")]
834 #[allow(dead_code)]
835 struct In {
836 checksum: HexBinary,
837 creator: String,
838 creator_data: HexBinary,
839 salt: HexBinary,
840 msg: Option<String>,
841 }
842
843 #[derive(Deserialize, Debug)]
844 #[serde(rename_all = "camelCase")]
845 #[allow(dead_code)]
846 struct Intermediate {
847 key: HexBinary,
848 address_data: HexBinary,
849 }
850
851 #[derive(Deserialize, Debug)]
852 #[serde(rename_all = "camelCase")]
853 #[allow(dead_code)]
854 struct Out {
855 address: String,
856 }
857
858 #[derive(Deserialize, Debug)]
859 #[allow(dead_code)]
860 struct Row {
861 #[serde(rename = "in")]
862 input: In,
863 intermediate: Intermediate,
864 out: Out,
865 }
866
867 fn read_tests() -> Vec<Row> {
868 use std::fs::File;
869 use std::io::BufReader;
870
871 let file = File::open(COSMOS_ED25519_TESTS_JSON).unwrap();
873 let reader = BufReader::new(file);
874
875 serde_json::from_reader(reader).unwrap()
876 }
877
878 for Row {
879 input,
880 intermediate,
881 out: _,
882 } in read_tests()
883 {
884 let msg = input.msg.map(|msg| msg.into_bytes()).unwrap_or_default();
885 let addr = instantiate2_address_impl(
886 &input.checksum,
887 &input.creator_data.into(),
888 &input.salt,
889 &msg,
890 32,
891 )
892 .unwrap();
893 assert_eq!(addr, intermediate.address_data);
894 }
895 }
896
897 #[test]
898 fn hash_works() {
899 let expected = [
901 195, 235, 23, 251, 9, 99, 177, 195, 81, 122, 182, 124, 36, 113, 245, 156, 76, 188, 221,
902 83, 181, 192, 227, 82, 100, 177, 161, 133, 240, 160, 5, 25,
903 ];
904 assert_eq!(hash("1", &[1]), expected);
905 }
906}