1use crate::access::Ownable;
3use crate::erc1155::erc1155_base::Erc1155Base;
4use crate::erc1155::errors::Error;
5use crate::erc1155::events::{TransferBatch, TransferSingle};
6use crate::erc1155::owned_erc1155::OwnedErc1155;
7use crate::erc1155::Erc1155;
8use odra::casper_types::{bytesrepr::Bytes, U256};
9use odra::prelude::*;
10
11#[odra::module(events = [TransferBatch, TransferSingle], errors = Error)]
14pub struct Erc1155Token {
15 core: SubModule<Erc1155Base>,
16 ownable: SubModule<Ownable>
17}
18
19#[odra::module]
20impl OwnedErc1155 for Erc1155Token {
21 fn init(&mut self) {
22 self.ownable.init();
23 }
24
25 fn balance_of(&self, owner: &Address, id: &U256) -> U256 {
26 self.core.balance_of(owner, id)
27 }
28 fn balance_of_batch(&self, owners: Vec<Address>, ids: Vec<U256>) -> Vec<U256> {
29 self.core.balance_of_batch(owners, ids)
30 }
31 fn set_approval_for_all(&mut self, operator: &Address, approved: bool) {
32 self.core.set_approval_for_all(operator, approved);
33 }
34 fn is_approved_for_all(&self, owner: &Address, operator: &Address) -> bool {
35 self.core.is_approved_for_all(owner, operator)
36 }
37 fn safe_transfer_from(
38 &mut self,
39 from: &Address,
40 to: &Address,
41 id: &U256,
42 amount: &U256,
43 data: &Option<Bytes>
44 ) {
45 self.core.safe_transfer_from(from, to, id, amount, data);
46 }
47
48 fn safe_batch_transfer_from(
49 &mut self,
50 from: &Address,
51 to: &Address,
52 ids: Vec<U256>,
53 amounts: Vec<U256>,
54 data: &Option<Bytes>
55 ) {
56 self.core
57 .safe_batch_transfer_from(from, to, ids, amounts, data);
58 }
59
60 fn renounce_ownership(&mut self) {
62 self.ownable.renounce_ownership();
63 }
64
65 fn transfer_ownership(&mut self, new_owner: &Address) {
66 self.ownable.transfer_ownership(new_owner);
67 }
68
69 fn owner(&self) -> Address {
70 self.ownable.get_owner()
71 }
72
73 fn mint(&mut self, to: &Address, id: &U256, amount: &U256, data: &Option<Bytes>) {
74 let caller = self.env().caller();
75 self.ownable.assert_owner(&caller);
76
77 let current_balance = self.core.balances.get_or_default(&(*to, *id));
78 self.core
79 .balances
80 .set(&(*to, *id), *amount + current_balance);
81
82 self.env().emit_event(TransferSingle {
83 operator: Some(caller),
84 from: None,
85 to: Some(*to),
86 id: *id,
87 value: *amount
88 });
89
90 self.core
91 .safe_transfer_acceptance_check(&caller, &caller, to, id, amount, data);
92 }
93
94 fn mint_batch(
95 &mut self,
96 to: &Address,
97 ids: Vec<U256>,
98 amounts: Vec<U256>,
99 data: &Option<Bytes>
100 ) {
101 if ids.len() != amounts.len() {
102 self.env().revert(Error::IdsAndAmountsLengthMismatch)
103 }
104
105 let caller = self.env().caller();
106 self.ownable.assert_owner(&caller);
107
108 for (id, amount) in ids.iter().zip(amounts.iter()) {
109 let current_balance = self.core.balances.get_or_default(&(*to, *id));
110 self.core
111 .balances
112 .set(&(*to, *id), *amount + current_balance);
113 }
114
115 self.env().emit_event(TransferBatch {
116 operator: Some(caller),
117 from: None,
118 to: Some(*to),
119 ids: ids.to_vec(),
120 values: amounts.to_vec()
121 });
122
123 self.core
124 .safe_batch_transfer_acceptance_check(&caller, &caller, to, ids, amounts, data);
125 }
126
127 fn burn(&mut self, from: &Address, id: &U256, amount: &U256) {
128 let caller = self.env().caller();
129 self.ownable.assert_owner(&caller);
130
131 let current_balance = self.core.balances.get_or_default(&(*from, *id));
132
133 if current_balance < *amount {
134 self.env().revert(Error::InsufficientBalance)
135 }
136
137 self.core
138 .balances
139 .set(&(*from, *id), current_balance - *amount);
140
141 self.env().emit_event(TransferSingle {
142 operator: Some(caller),
143 from: Some(*from),
144 to: None,
145 id: *id,
146 value: *amount
147 });
148 }
149
150 fn burn_batch(&mut self, from: &Address, ids: Vec<U256>, amounts: Vec<U256>) {
151 if ids.len() != amounts.len() {
152 self.env().revert(Error::IdsAndAmountsLengthMismatch)
153 }
154
155 let caller = self.env().caller();
156 self.ownable.assert_owner(&caller);
157
158 for (id, amount) in ids.iter().zip(amounts.iter()) {
159 let current_balance = self.core.balances.get_or_default(&(*from, *id));
160
161 if current_balance < *amount {
162 self.env().revert(Error::InsufficientBalance)
163 }
164 self.core
165 .balances
166 .set(&(*from, *id), current_balance - *amount);
167 }
168
169 self.env().emit_event(TransferBatch {
170 operator: Some(caller),
171 from: Some(*from),
172 to: None,
173 ids: ids.to_vec(),
174 values: amounts.to_vec()
175 });
176 }
177}
178
179#[cfg(test)]
180mod tests {
181 use crate::erc1155::errors::Error;
182 use crate::erc1155::errors::Error::InsufficientBalance;
183 use crate::erc1155::events::{ApprovalForAll, TransferBatch, TransferSingle};
184 use crate::erc1155::owned_erc1155::OwnedErc1155;
185 use crate::erc1155_receiver::events::{BatchReceived, SingleReceived};
186 use crate::erc1155_receiver::Erc1155Receiver;
187 use crate::erc1155_token::Erc1155TokenHostRef;
188 use crate::wrapped_native::WrappedNativeToken;
189 use odra::host::{Deployer, HostEnv, HostRef, NoArgs};
190 use odra::prelude::*;
191 use odra::{
192 casper_types::{bytesrepr::Bytes, U256},
193 VmError
194 };
195
196 use super::Erc1155Token;
197
198 struct TokenEnv {
199 env: HostEnv,
200 token: Erc1155TokenHostRef,
201 alice: Address,
202 bob: Address,
203 owner: Address
204 }
205
206 fn setup() -> TokenEnv {
207 let env = odra_test::env();
208
209 TokenEnv {
210 env: env.clone(),
211 token: Erc1155Token::deploy(&env, NoArgs),
212 alice: env.get_account(1),
213 bob: env.get_account(2),
214 owner: env.get_account(0)
215 }
216 }
217
218 #[test]
219 fn mint() {
220 let mut env = setup();
222
223 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
225
226 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
228
229 let contract = env.token;
231 env.env.emitted_event(
232 contract.address(),
233 &TransferSingle {
234 operator: Some(env.owner),
235 from: None,
236 to: Some(env.alice),
237 id: U256::one(),
238 value: 100.into()
239 }
240 );
241 }
242
243 #[test]
244 fn mint_batch() {
245 let mut env = setup();
247
248 env.token.mint_batch(
250 &env.alice,
251 vec![U256::one(), U256::from(2)],
252 vec![100.into(), 200.into()],
253 &None
254 );
255
256 env.env.emitted_event(
258 env.token.address(),
259 &TransferBatch {
260 operator: Some(env.owner),
261 from: None,
262 to: Some(env.alice),
263 ids: vec![U256::one(), U256::from(2)],
264 values: vec![100.into(), 200.into()]
265 }
266 );
267
268 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
270 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 200.into());
271 }
272
273 #[test]
274 fn mint_batch_errors() {
275 let mut env = setup();
277 let err = env
279 .token
280 .try_mint_batch(
281 &env.alice,
282 [U256::one(), U256::from(2)].to_vec(),
283 [100.into()].to_vec(),
284 &None
285 )
286 .unwrap_err();
287 assert_eq!(err, Error::IdsAndAmountsLengthMismatch.into());
288 }
289
290 #[test]
291 fn burn() {
292 let mut env = setup();
294
295 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
297
298 env.token.burn(&env.alice, &U256::one(), &50.into());
300
301 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
303
304 let contract = env.token;
306 env.env.emitted_event(
307 contract.address(),
308 &TransferSingle {
309 operator: Some(env.owner),
310 from: Some(env.alice),
311 to: None,
312 id: U256::one(),
313 value: 50.into()
314 }
315 );
316 }
317
318 #[test]
319 fn burn_errors() {
320 let mut env = setup();
322
323 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
325 let err = env
327 .token
328 .try_burn(&env.alice, &U256::one(), &150.into())
329 .unwrap_err();
330 assert_eq!(err, InsufficientBalance.into());
331
332 let mut env = setup();
334 let err = env
336 .token
337 .try_burn(&env.alice, &U256::one(), &150.into())
338 .unwrap_err();
339 assert_eq!(err, InsufficientBalance.into());
340 }
341
342 #[test]
343 fn burn_batch() {
344 let mut env = setup();
346
347 env.token.mint_batch(
349 &env.alice,
350 [U256::one(), U256::from(2)].to_vec(),
351 [100.into(), 200.into()].to_vec(),
352 &None
353 );
354
355 env.token.burn_batch(
357 &env.alice,
358 [U256::one(), U256::from(2)].to_vec(),
359 [50.into(), 100.into()].to_vec()
360 );
361
362 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
364 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 100.into());
365
366 let contract = env.token;
368 env.env.emitted_event(
369 contract.address(),
370 &TransferBatch {
371 operator: Some(env.owner),
372 from: Some(env.alice),
373 to: None,
374 ids: vec![U256::one(), U256::from(2)],
375 values: vec![50.into(), 100.into()]
376 }
377 );
378 }
379
380 #[test]
381 fn burn_batch_errors() {
382 let mut env = setup();
384
385 env.token.mint_batch(
387 &env.alice,
388 [U256::one(), U256::from(2)].to_vec(),
389 [100.into(), 200.into()].to_vec(),
390 &None
391 );
392
393 let err = env
395 .token
396 .try_burn_batch(
397 &env.alice,
398 [U256::one(), U256::from(2)].to_vec(),
399 [50.into()].to_vec()
400 )
401 .unwrap_err();
402 assert_eq!(err, Error::IdsAndAmountsLengthMismatch.into());
403
404 let mut env = setup();
406
407 env.token.mint_batch(
409 &env.alice,
410 [U256::one(), U256::from(2)].to_vec(),
411 [100.into(), 200.into()].to_vec(),
412 &None
413 );
414
415 let err = env
417 .token
418 .try_burn_batch(
419 &env.alice,
420 [U256::one(), U256::from(2)].to_vec(),
421 [150.into(), 300.into()].to_vec()
422 )
423 .unwrap_err();
424 assert_eq!(err, InsufficientBalance.into());
425
426 let mut env = setup();
428
429 let err = env
431 .token
432 .try_burn_batch(
433 &env.alice,
434 [U256::one(), U256::from(2)].to_vec(),
435 [150.into(), 300.into()].to_vec()
436 )
437 .unwrap_err();
438 assert_eq!(err, InsufficientBalance.into());
439 }
440
441 #[test]
442 fn balance_of() {
443 let mut env = setup();
445
446 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
448 env.token
449 .mint(&env.alice, &U256::from(2), &200.into(), &None);
450 env.token.mint(&env.bob, &U256::one(), &300.into(), &None);
451
452 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
454 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 200.into());
455 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 300.into());
456 assert_eq!(env.token.balance_of(&env.bob, &U256::from(2)), 0.into());
457 }
458
459 #[test]
460 fn balance_of_batch() {
461 let mut env = setup();
463
464 env.token.mint_batch(
466 &env.alice,
467 [U256::one(), U256::from(2)].to_vec(),
468 [100.into(), 200.into()].to_vec(),
469 &None
470 );
471 env.token.mint_batch(
472 &env.bob,
473 [U256::one(), U256::from(2)].to_vec(),
474 [300.into(), 400.into()].to_vec(),
475 &None
476 );
477
478 assert_eq!(
480 env.token.balance_of_batch(
481 [env.alice, env.alice, env.alice, env.bob, env.bob, env.bob].to_vec(),
482 [
483 U256::one(),
484 U256::from(2),
485 U256::from(3),
486 U256::one(),
487 U256::from(2),
488 U256::from(3)
489 ]
490 .to_vec()
491 ),
492 [
494 U256::from(100),
495 U256::from(200),
496 U256::zero(),
497 U256::from(300),
498 U256::from(400),
499 U256::zero()
500 ]
501 .to_vec()
502 );
503 }
504
505 #[test]
506 fn balance_of_batch_errors() {
507 let mut env = setup();
509
510 env.token.mint_batch(
512 &env.alice,
513 [U256::one(), U256::from(2)].to_vec(),
514 [100.into(), 200.into()].to_vec(),
515 &None
516 );
517
518 let err = env
520 .token
521 .try_balance_of_batch(
522 [env.alice, env.alice, env.alice].to_vec(),
523 [U256::one(), U256::from(2)].to_vec()
524 )
525 .unwrap_err();
526 assert_eq!(err, Error::AccountsAndIdsLengthMismatch.into());
527 }
528
529 #[test]
530 fn set_approval_for_all() {
531 let mut env = setup();
533
534 env.env.set_caller(env.alice);
536 env.token.set_approval_for_all(&env.bob, true);
537
538 assert!(env.token.is_approved_for_all(&env.alice, &env.bob));
540
541 env.env.emitted_event(
543 env.token.address(),
544 &ApprovalForAll {
545 owner: env.alice,
546 operator: env.bob,
547 approved: true
548 }
549 );
550 }
551
552 #[test]
553 fn unset_approval_for_all() {
554 let mut env = setup();
556
557 env.env.set_caller(env.alice);
559 env.token.set_approval_for_all(&env.bob, true);
560
561 env.env.set_caller(env.alice);
563 env.token.set_approval_for_all(&env.bob, false);
564
565 assert!(!env.token.is_approved_for_all(&env.alice, &env.bob));
567
568 let contract = env.token;
570 env.env.emitted_event(
571 contract.address(),
572 &ApprovalForAll {
573 owner: env.alice,
574 operator: env.bob,
575 approved: false
576 }
577 );
578 }
579
580 #[test]
581 fn set_approval_to_self() {
582 let mut env = setup();
584
585 env.env.set_caller(env.alice);
587 let err = env
588 .token
589 .try_set_approval_for_all(&env.alice, true)
590 .unwrap_err();
591 assert_eq!(err, Error::ApprovalForSelf.into());
592 }
593
594 #[test]
595 fn safe_transfer_from() {
596 let mut env = setup();
598
599 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
601
602 env.env.set_caller(env.alice);
604 env.token
605 .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
606
607 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
609 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
610
611 let contract = env.token;
613 env.env.emitted_event(
614 contract.address(),
615 &TransferSingle {
616 operator: Some(env.alice),
617 from: Some(env.alice),
618 to: Some(env.bob),
619 id: U256::one(),
620 value: 50.into()
621 }
622 );
623 }
624
625 #[test]
626 fn safe_transfer_from_approved() {
627 let mut env = setup();
629
630 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
632
633 env.env.set_caller(env.alice);
635 env.token.set_approval_for_all(&env.bob, true);
636
637 env.env.set_caller(env.bob);
639 env.token
640 .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
641
642 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
644 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
645
646 let contract = env.token;
648 env.env.emitted_event(
649 contract.address(),
650 &TransferSingle {
651 operator: Some(env.bob),
652 from: Some(env.alice),
653 to: Some(env.bob),
654 id: U256::one(),
655 value: 50.into()
656 }
657 );
658 }
659
660 #[test]
661 fn safe_transfer_from_errors() {
662 let mut env = setup();
664
665 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
667
668 env.env.set_caller(env.alice);
670 let err = env
671 .token
672 .try_safe_transfer_from(&env.alice, &env.bob, &U256::one(), &200.into(), &None)
673 .unwrap_err();
674 assert_eq!(err, Error::InsufficientBalance.into());
675
676 let mut env = setup();
679 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
681
682 env.env.set_caller(env.bob);
684 let err = env
685 .token
686 .try_safe_transfer_from(&env.alice, &env.bob, &U256::one(), &100.into(), &None)
687 .unwrap_err();
688 assert_eq!(err, Error::NotAnOwnerOrApproved.into());
689 }
690
691 #[test]
692 fn safe_batch_transfer_from() {
693 let mut env = setup();
695
696 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
698 env.token
699 .mint(&env.alice, &U256::from(2), &200.into(), &None);
700
701 env.env.set_caller(env.alice);
703 env.token.safe_batch_transfer_from(
704 &env.alice,
705 &env.bob,
706 [U256::one(), U256::from(2)].to_vec(),
707 [50.into(), 100.into()].to_vec(),
708 &None
709 );
710
711 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
713 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 100.into());
714 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
715 assert_eq!(env.token.balance_of(&env.bob, &U256::from(2)), 100.into());
716
717 let contract = env.token;
719 env.env.emitted_event(
720 contract.address(),
721 &TransferBatch {
722 operator: Some(env.alice),
723 from: Some(env.alice),
724 to: Some(env.bob),
725 ids: vec![U256::one(), U256::from(2)],
726 values: vec![50.into(), 100.into()]
727 }
728 );
729 }
730
731 #[test]
732 fn safe_batch_transfer_from_approved() {
733 let mut env = setup();
735
736 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
738 env.token
739 .mint(&env.alice, &U256::from(2), &200.into(), &None);
740
741 env.env.set_caller(env.alice);
743 env.token.set_approval_for_all(&env.bob, true);
744
745 env.env.set_caller(env.bob);
747 env.token.safe_batch_transfer_from(
748 &env.alice,
749 &env.bob,
750 [U256::one(), U256::from(2)].to_vec(),
751 [50.into(), 100.into()].to_vec(),
752 &None
753 );
754
755 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
757 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 100.into());
758 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
759 assert_eq!(env.token.balance_of(&env.bob, &U256::from(2)), 100.into());
760
761 let contract = env.token;
763 env.env.emitted_event(
764 contract.address(),
765 &TransferBatch {
766 operator: Some(env.bob),
767 from: Some(env.alice),
768 to: Some(env.bob),
769 ids: vec![U256::one(), U256::from(2)],
770 values: vec![50.into(), 100.into()]
771 }
772 );
773 }
774
775 #[test]
776 fn safe_batch_transfer_errors() {
777 let mut env = setup();
779
780 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
782 env.token
783 .mint(&env.alice, &U256::from(2), &200.into(), &None);
784 env.env.set_caller(env.alice);
786 let err = env
787 .token
788 .try_safe_batch_transfer_from(
789 &env.alice,
790 &env.bob,
791 [U256::one(), U256::from(2)].to_vec(),
792 [50.into(), 300.into()].to_vec(),
793 &None
794 )
795 .unwrap_err();
796 assert_eq!(err, Error::InsufficientBalance.into());
797
798 let mut env = setup();
800
801 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
803 env.token
804 .mint(&env.alice, &U256::from(2), &200.into(), &None);
805 env.env.set_caller(env.bob);
807 let err = env
808 .token
809 .try_safe_batch_transfer_from(
810 &env.alice,
811 &env.bob,
812 [U256::one(), U256::from(2)].to_vec(),
813 [50.into(), 100.into()].to_vec(),
814 &None
815 )
816 .unwrap_err();
817 assert_eq!(err, Error::NotAnOwnerOrApproved.into());
818 }
819
820 #[test]
821 fn safe_transfer_to_valid_receiver() {
822 let mut env = setup();
824 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
827 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
829
830 env.env.set_caller(env.alice);
832 env.token.safe_transfer_from(
833 &env.alice,
834 receiver.address(),
835 &U256::one(),
836 &100.into(),
837 &None
838 );
839
840 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
842 assert_eq!(
843 env.token.balance_of(receiver.address(), &U256::one()),
844 100.into()
845 );
846
847 env.env.emitted_event(
849 receiver.address(),
850 &SingleReceived {
851 operator: Some(env.alice),
852 from: Some(env.alice),
853 token_id: U256::one(),
854 amount: 100.into(),
855 data: None
856 }
857 );
858 }
859
860 #[test]
861 fn safe_transfer_to_valid_receiver_with_data() {
862 let mut env = setup();
864 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
866 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
868
869 env.env.set_caller(env.alice);
871 env.token.safe_transfer_from(
872 &env.alice,
873 receiver.address(),
874 &U256::one(),
875 &100.into(),
876 &Some(Bytes::from(b"data".to_vec()))
877 );
878
879 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
881 assert_eq!(
882 env.token.balance_of(receiver.address(), &U256::one()),
883 100.into()
884 );
885
886 env.env.emitted_event(
888 receiver.address(),
889 &SingleReceived {
890 operator: Some(env.alice),
891 from: Some(env.alice),
892 token_id: U256::one(),
893 amount: 100.into(),
894 data: Some(Bytes::from(b"data".to_vec()))
895 }
896 );
897 }
898
899 #[test]
900 fn safe_transfer_to_invalid_receiver() {
901 let mut env = setup();
903 let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
905 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
907
908 env.env.set_caller(env.alice);
911 let err = env.token.try_safe_transfer_from(
912 &env.alice,
913 receiver.address(),
914 &U256::one(),
915 &100.into(),
916 &None
917 );
918 assert_eq!(
919 err,
920 Err(OdraError::VmError(VmError::NoSuchMethod(
921 "on_erc1155_received".to_string()
922 )))
923 );
924 }
925
926 #[test]
927 fn safe_batch_transfer_to_valid_receiver() {
928 let mut env = setup();
930 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
932 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
934 env.token
935 .mint(&env.alice, &U256::from(2), &100.into(), &None);
936
937 env.env.set_caller(env.alice);
939 env.token.safe_batch_transfer_from(
940 &env.alice,
941 receiver.address(),
942 [U256::one(), U256::from(2)].to_vec(),
943 [100.into(), 100.into()].to_vec(),
944 &None
945 );
946
947 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
949 assert_eq!(
950 env.token.balance_of(receiver.address(), &U256::one()),
951 100.into()
952 );
953 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 0.into());
954 assert_eq!(
955 env.token.balance_of(receiver.address(), &U256::from(2)),
956 100.into()
957 );
958
959 env.env.emitted_event(
961 receiver.address(),
962 &BatchReceived {
963 operator: Some(env.alice),
964 from: Some(env.alice),
965 token_ids: [U256::one(), U256::from(2)].to_vec(),
966 amounts: [100.into(), 100.into()].to_vec(),
967 data: None
968 }
969 );
970 }
971
972 #[test]
973 fn safe_batch_transfer_to_valid_receiver_with_data() {
974 let mut env = setup();
976 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
978 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
980 env.token
981 .mint(&env.alice, &U256::from(2), &100.into(), &None);
982
983 env.env.set_caller(env.alice);
985 env.token.safe_batch_transfer_from(
986 &env.alice,
987 receiver.address(),
988 [U256::one(), U256::from(2)].to_vec(),
989 [100.into(), 100.into()].to_vec(),
990 &Some(Bytes::from(b"data".to_vec()))
991 );
992
993 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
995 assert_eq!(
996 env.token.balance_of(receiver.address(), &U256::one()),
997 100.into()
998 );
999 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 0.into());
1000 assert_eq!(
1001 env.token.balance_of(receiver.address(), &U256::from(2)),
1002 100.into()
1003 );
1004
1005 env.env.emitted_event(
1007 receiver.address(),
1008 &BatchReceived {
1009 operator: Some(env.alice),
1010 from: Some(env.alice),
1011 token_ids: [U256::one(), U256::from(2)].to_vec(),
1012 amounts: [100.into(), 100.into()].to_vec(),
1013 data: Some(Bytes::from(b"data".to_vec()))
1014 }
1015 );
1016 }
1017
1018 #[test]
1019 fn safe_batch_transfer_to_invalid_receiver() {
1020 let mut env = setup();
1022 let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
1024 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
1026 env.token
1027 .mint(&env.alice, &U256::from(2), &100.into(), &None);
1028
1029 env.env.set_caller(env.alice);
1032 let err = env
1033 .token
1034 .try_safe_batch_transfer_from(
1035 &env.alice,
1036 receiver.address(),
1037 vec![U256::one(), U256::from(2)],
1038 vec![100.into(), 100.into()],
1039 &None
1040 )
1041 .unwrap_err();
1042 assert_eq!(
1043 err,
1044 OdraError::VmError(VmError::NoSuchMethod(
1045 "on_erc1155_batch_received".to_string()
1046 ))
1047 );
1048 }
1049}