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 let caller = self.env().caller();
23 self.ownable.init(caller);
24 }
25
26 fn balance_of(&self, owner: &Address, id: &U256) -> U256 {
27 self.core.balance_of(owner, id)
28 }
29 fn balance_of_batch(&self, owners: Vec<Address>, ids: Vec<U256>) -> Vec<U256> {
30 self.core.balance_of_batch(owners, ids)
31 }
32 fn set_approval_for_all(&mut self, operator: &Address, approved: bool) {
33 self.core.set_approval_for_all(operator, approved);
34 }
35 fn is_approved_for_all(&self, owner: &Address, operator: &Address) -> bool {
36 self.core.is_approved_for_all(owner, operator)
37 }
38 fn safe_transfer_from(
39 &mut self,
40 from: &Address,
41 to: &Address,
42 id: &U256,
43 amount: &U256,
44 data: &Option<Bytes>
45 ) {
46 self.core.safe_transfer_from(from, to, id, amount, data);
47 }
48
49 fn safe_batch_transfer_from(
50 &mut self,
51 from: &Address,
52 to: &Address,
53 ids: Vec<U256>,
54 amounts: Vec<U256>,
55 data: &Option<Bytes>
56 ) {
57 self.core
58 .safe_batch_transfer_from(from, to, ids, amounts, data);
59 }
60
61 fn renounce_ownership(&mut self) {
63 self.ownable.renounce_ownership();
64 }
65
66 fn transfer_ownership(&mut self, new_owner: &Address) {
67 self.ownable.transfer_ownership(new_owner);
68 }
69
70 fn owner(&self) -> Address {
71 self.ownable.get_owner()
72 }
73
74 fn mint(&mut self, to: &Address, id: &U256, amount: &U256, data: &Option<Bytes>) {
75 let caller = self.env().caller();
76 self.ownable.assert_owner(&caller);
77
78 let current_balance = self.core.balances.get_or_default(&(*to, *id));
79 self.core
80 .balances
81 .set(&(*to, *id), *amount + current_balance);
82
83 self.env().emit_event(TransferSingle {
84 operator: Some(caller),
85 from: None,
86 to: Some(*to),
87 id: *id,
88 value: *amount
89 });
90
91 self.core
92 .safe_transfer_acceptance_check(&caller, &caller, to, id, amount, data);
93 }
94
95 fn mint_batch(
96 &mut self,
97 to: &Address,
98 ids: Vec<U256>,
99 amounts: Vec<U256>,
100 data: &Option<Bytes>
101 ) {
102 if ids.len() != amounts.len() {
103 self.env().revert(Error::IdsAndAmountsLengthMismatch)
104 }
105
106 let caller = self.env().caller();
107 self.ownable.assert_owner(&caller);
108
109 for (id, amount) in ids.iter().zip(amounts.iter()) {
110 let current_balance = self.core.balances.get_or_default(&(*to, *id));
111 self.core
112 .balances
113 .set(&(*to, *id), *amount + current_balance);
114 }
115
116 self.env().emit_event(TransferBatch {
117 operator: Some(caller),
118 from: None,
119 to: Some(*to),
120 ids: ids.to_vec(),
121 values: amounts.to_vec()
122 });
123
124 self.core
125 .safe_batch_transfer_acceptance_check(&caller, &caller, to, ids, amounts, data);
126 }
127
128 fn burn(&mut self, from: &Address, id: &U256, amount: &U256) {
129 let caller = self.env().caller();
130 self.ownable.assert_owner(&caller);
131
132 let current_balance = self.core.balances.get_or_default(&(*from, *id));
133
134 if current_balance < *amount {
135 self.env().revert(Error::InsufficientBalance)
136 }
137
138 self.core
139 .balances
140 .set(&(*from, *id), current_balance - *amount);
141
142 self.env().emit_event(TransferSingle {
143 operator: Some(caller),
144 from: Some(*from),
145 to: None,
146 id: *id,
147 value: *amount
148 });
149 }
150
151 fn burn_batch(&mut self, from: &Address, ids: Vec<U256>, amounts: Vec<U256>) {
152 if ids.len() != amounts.len() {
153 self.env().revert(Error::IdsAndAmountsLengthMismatch)
154 }
155
156 let caller = self.env().caller();
157 self.ownable.assert_owner(&caller);
158
159 for (id, amount) in ids.iter().zip(amounts.iter()) {
160 let current_balance = self.core.balances.get_or_default(&(*from, *id));
161
162 if current_balance < *amount {
163 self.env().revert(Error::InsufficientBalance)
164 }
165 self.core
166 .balances
167 .set(&(*from, *id), current_balance - *amount);
168 }
169
170 self.env().emit_event(TransferBatch {
171 operator: Some(caller),
172 from: Some(*from),
173 to: None,
174 ids: ids.to_vec(),
175 values: amounts.to_vec()
176 });
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use crate::erc1155::errors::Error;
183 use crate::erc1155::errors::Error::InsufficientBalance;
184 use crate::erc1155::events::{ApprovalForAll, TransferBatch, TransferSingle};
185 use crate::erc1155::owned_erc1155::OwnedErc1155;
186 use crate::erc1155_receiver::events::{BatchReceived, SingleReceived};
187 use crate::erc1155_receiver::Erc1155Receiver;
188 use crate::erc1155_token::Erc1155TokenHostRef;
189 use crate::wrapped_native::WrappedNativeToken;
190 use odra::host::{Deployer, HostEnv, NoArgs};
191 use odra::prelude::*;
192 use odra::{
193 casper_types::{bytesrepr::Bytes, U256},
194 VmError
195 };
196
197 use super::Erc1155Token;
198
199 struct TokenEnv {
200 env: HostEnv,
201 token: Erc1155TokenHostRef,
202 alice: Address,
203 bob: Address,
204 owner: Address
205 }
206
207 fn setup() -> TokenEnv {
208 let env = odra_test::env();
209
210 TokenEnv {
211 env: env.clone(),
212 token: Erc1155Token::deploy(&env, NoArgs),
213 alice: env.get_account(1),
214 bob: env.get_account(2),
215 owner: env.get_account(0)
216 }
217 }
218
219 #[test]
220 fn mint() {
221 let mut env = setup();
223
224 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
226
227 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
229
230 let contract = env.token;
232 env.env.emitted_event(
233 &contract,
234 TransferSingle {
235 operator: Some(env.owner),
236 from: None,
237 to: Some(env.alice),
238 id: U256::one(),
239 value: 100.into()
240 }
241 );
242 }
243
244 #[test]
245 fn mint_batch() {
246 let mut env = setup();
248
249 env.token.mint_batch(
251 &env.alice,
252 vec![U256::one(), U256::from(2)],
253 vec![100.into(), 200.into()],
254 &None
255 );
256
257 env.env.emitted_event(
259 &env.token,
260 TransferBatch {
261 operator: Some(env.owner),
262 from: None,
263 to: Some(env.alice),
264 ids: vec![U256::one(), U256::from(2)],
265 values: vec![100.into(), 200.into()]
266 }
267 );
268
269 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
271 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 200.into());
272 }
273
274 #[test]
275 fn mint_batch_errors() {
276 let mut env = setup();
278 let err = env
280 .token
281 .try_mint_batch(
282 &env.alice,
283 [U256::one(), U256::from(2)].to_vec(),
284 [100.into()].to_vec(),
285 &None
286 )
287 .unwrap_err();
288 assert_eq!(err, Error::IdsAndAmountsLengthMismatch.into());
289 }
290
291 #[test]
292 fn burn() {
293 let mut env = setup();
295
296 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
298
299 env.token.burn(&env.alice, &U256::one(), &50.into());
301
302 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
304
305 let contract = env.token;
307 env.env.emitted_event(
308 &contract,
309 TransferSingle {
310 operator: Some(env.owner),
311 from: Some(env.alice),
312 to: None,
313 id: U256::one(),
314 value: 50.into()
315 }
316 );
317 }
318
319 #[test]
320 fn burn_errors() {
321 let mut env = setup();
323
324 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
326 let err = env
328 .token
329 .try_burn(&env.alice, &U256::one(), &150.into())
330 .unwrap_err();
331 assert_eq!(err, InsufficientBalance.into());
332
333 let mut env = setup();
335 let err = env
337 .token
338 .try_burn(&env.alice, &U256::one(), &150.into())
339 .unwrap_err();
340 assert_eq!(err, InsufficientBalance.into());
341 }
342
343 #[test]
344 fn burn_batch() {
345 let mut env = setup();
347
348 env.token.mint_batch(
350 &env.alice,
351 [U256::one(), U256::from(2)].to_vec(),
352 [100.into(), 200.into()].to_vec(),
353 &None
354 );
355
356 env.token.burn_batch(
358 &env.alice,
359 [U256::one(), U256::from(2)].to_vec(),
360 [50.into(), 100.into()].to_vec()
361 );
362
363 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
365 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 100.into());
366
367 let contract = env.token;
369 env.env.emitted_event(
370 &contract,
371 TransferBatch {
372 operator: Some(env.owner),
373 from: Some(env.alice),
374 to: None,
375 ids: vec![U256::one(), U256::from(2)],
376 values: vec![50.into(), 100.into()]
377 }
378 );
379 }
380
381 #[test]
382 fn burn_batch_errors() {
383 let mut env = setup();
385
386 env.token.mint_batch(
388 &env.alice,
389 [U256::one(), U256::from(2)].to_vec(),
390 [100.into(), 200.into()].to_vec(),
391 &None
392 );
393
394 let err = env
396 .token
397 .try_burn_batch(
398 &env.alice,
399 [U256::one(), U256::from(2)].to_vec(),
400 [50.into()].to_vec()
401 )
402 .unwrap_err();
403 assert_eq!(err, Error::IdsAndAmountsLengthMismatch.into());
404
405 let mut env = setup();
407
408 env.token.mint_batch(
410 &env.alice,
411 [U256::one(), U256::from(2)].to_vec(),
412 [100.into(), 200.into()].to_vec(),
413 &None
414 );
415
416 let err = env
418 .token
419 .try_burn_batch(
420 &env.alice,
421 [U256::one(), U256::from(2)].to_vec(),
422 [150.into(), 300.into()].to_vec()
423 )
424 .unwrap_err();
425 assert_eq!(err, InsufficientBalance.into());
426
427 let mut env = setup();
429
430 let err = env
432 .token
433 .try_burn_batch(
434 &env.alice,
435 [U256::one(), U256::from(2)].to_vec(),
436 [150.into(), 300.into()].to_vec()
437 )
438 .unwrap_err();
439 assert_eq!(err, InsufficientBalance.into());
440 }
441
442 #[test]
443 fn balance_of() {
444 let mut env = setup();
446
447 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
449 env.token
450 .mint(&env.alice, &U256::from(2), &200.into(), &None);
451 env.token.mint(&env.bob, &U256::one(), &300.into(), &None);
452
453 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
455 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 200.into());
456 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 300.into());
457 assert_eq!(env.token.balance_of(&env.bob, &U256::from(2)), 0.into());
458 }
459
460 #[test]
461 fn balance_of_batch() {
462 let mut env = setup();
464
465 env.token.mint_batch(
467 &env.alice,
468 [U256::one(), U256::from(2)].to_vec(),
469 [100.into(), 200.into()].to_vec(),
470 &None
471 );
472 env.token.mint_batch(
473 &env.bob,
474 [U256::one(), U256::from(2)].to_vec(),
475 [300.into(), 400.into()].to_vec(),
476 &None
477 );
478
479 assert_eq!(
481 env.token.balance_of_batch(
482 [env.alice, env.alice, env.alice, env.bob, env.bob, env.bob].to_vec(),
483 [
484 U256::one(),
485 U256::from(2),
486 U256::from(3),
487 U256::one(),
488 U256::from(2),
489 U256::from(3)
490 ]
491 .to_vec()
492 ),
493 [
495 U256::from(100),
496 U256::from(200),
497 U256::zero(),
498 U256::from(300),
499 U256::from(400),
500 U256::zero()
501 ]
502 .to_vec()
503 );
504 }
505
506 #[test]
507 fn balance_of_batch_errors() {
508 let mut env = setup();
510
511 env.token.mint_batch(
513 &env.alice,
514 [U256::one(), U256::from(2)].to_vec(),
515 [100.into(), 200.into()].to_vec(),
516 &None
517 );
518
519 let err = env
521 .token
522 .try_balance_of_batch(
523 [env.alice, env.alice, env.alice].to_vec(),
524 [U256::one(), U256::from(2)].to_vec()
525 )
526 .unwrap_err();
527 assert_eq!(err, Error::AccountsAndIdsLengthMismatch.into());
528 }
529
530 #[test]
531 fn set_approval_for_all() {
532 let mut env = setup();
534
535 env.env.set_caller(env.alice);
537 env.token.set_approval_for_all(&env.bob, true);
538
539 assert!(env.token.is_approved_for_all(&env.alice, &env.bob));
541
542 env.env.emitted_event(
544 &env.token,
545 ApprovalForAll {
546 owner: env.alice,
547 operator: env.bob,
548 approved: true
549 }
550 );
551 }
552
553 #[test]
554 fn unset_approval_for_all() {
555 let mut env = setup();
557
558 env.env.set_caller(env.alice);
560 env.token.set_approval_for_all(&env.bob, true);
561
562 env.env.set_caller(env.alice);
564 env.token.set_approval_for_all(&env.bob, false);
565
566 assert!(!env.token.is_approved_for_all(&env.alice, &env.bob));
568
569 let contract = env.token;
571 env.env.emitted_event(
572 &contract,
573 ApprovalForAll {
574 owner: env.alice,
575 operator: env.bob,
576 approved: false
577 }
578 );
579 }
580
581 #[test]
582 fn set_approval_to_self() {
583 let mut env = setup();
585
586 env.env.set_caller(env.alice);
588 let err = env
589 .token
590 .try_set_approval_for_all(&env.alice, true)
591 .unwrap_err();
592 assert_eq!(err, Error::ApprovalForSelf.into());
593 }
594
595 #[test]
596 fn safe_transfer_from() {
597 let mut env = setup();
599
600 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
602
603 env.env.set_caller(env.alice);
605 env.token
606 .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
607
608 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
610 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
611
612 let contract = env.token;
614 env.env.emitted_event(
615 &contract,
616 TransferSingle {
617 operator: Some(env.alice),
618 from: Some(env.alice),
619 to: Some(env.bob),
620 id: U256::one(),
621 value: 50.into()
622 }
623 );
624 }
625
626 #[test]
627 fn safe_transfer_from_approved() {
628 let mut env = setup();
630
631 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
633
634 env.env.set_caller(env.alice);
636 env.token.set_approval_for_all(&env.bob, true);
637
638 env.env.set_caller(env.bob);
640 env.token
641 .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
642
643 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
645 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
646
647 let contract = env.token;
649 env.env.emitted_event(
650 &contract,
651 TransferSingle {
652 operator: Some(env.bob),
653 from: Some(env.alice),
654 to: Some(env.bob),
655 id: U256::one(),
656 value: 50.into()
657 }
658 );
659 }
660
661 #[test]
662 fn safe_transfer_from_errors() {
663 let mut env = setup();
665
666 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
668
669 env.env.set_caller(env.alice);
671 let err = env
672 .token
673 .try_safe_transfer_from(&env.alice, &env.bob, &U256::one(), &200.into(), &None)
674 .unwrap_err();
675 assert_eq!(err, Error::InsufficientBalance.into());
676
677 let mut env = setup();
680 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
682
683 env.env.set_caller(env.bob);
685 let err = env
686 .token
687 .try_safe_transfer_from(&env.alice, &env.bob, &U256::one(), &100.into(), &None)
688 .unwrap_err();
689 assert_eq!(err, Error::NotAnOwnerOrApproved.into());
690 }
691
692 #[test]
693 fn safe_batch_transfer_from() {
694 let mut env = setup();
696
697 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
699 env.token
700 .mint(&env.alice, &U256::from(2), &200.into(), &None);
701
702 env.env.set_caller(env.alice);
704 env.token.safe_batch_transfer_from(
705 &env.alice,
706 &env.bob,
707 [U256::one(), U256::from(2)].to_vec(),
708 [50.into(), 100.into()].to_vec(),
709 &None
710 );
711
712 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
714 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 100.into());
715 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
716 assert_eq!(env.token.balance_of(&env.bob, &U256::from(2)), 100.into());
717
718 let contract = env.token;
720 env.env.emitted_event(
721 &contract,
722 TransferBatch {
723 operator: Some(env.alice),
724 from: Some(env.alice),
725 to: Some(env.bob),
726 ids: vec![U256::one(), U256::from(2)],
727 values: vec![50.into(), 100.into()]
728 }
729 );
730 }
731
732 #[test]
733 fn safe_batch_transfer_from_approved() {
734 let mut env = setup();
736
737 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
739 env.token
740 .mint(&env.alice, &U256::from(2), &200.into(), &None);
741
742 env.env.set_caller(env.alice);
744 env.token.set_approval_for_all(&env.bob, true);
745
746 env.env.set_caller(env.bob);
748 env.token.safe_batch_transfer_from(
749 &env.alice,
750 &env.bob,
751 [U256::one(), U256::from(2)].to_vec(),
752 [50.into(), 100.into()].to_vec(),
753 &None
754 );
755
756 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
758 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 100.into());
759 assert_eq!(env.token.balance_of(&env.bob, &U256::one()), 50.into());
760 assert_eq!(env.token.balance_of(&env.bob, &U256::from(2)), 100.into());
761
762 let contract = env.token;
764 env.env.emitted_event(
765 &contract,
766 TransferBatch {
767 operator: Some(env.bob),
768 from: Some(env.alice),
769 to: Some(env.bob),
770 ids: vec![U256::one(), U256::from(2)],
771 values: vec![50.into(), 100.into()]
772 }
773 );
774 }
775
776 #[test]
777 fn safe_batch_transfer_errors() {
778 let mut env = setup();
780
781 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
783 env.token
784 .mint(&env.alice, &U256::from(2), &200.into(), &None);
785 env.env.set_caller(env.alice);
787 let err = env
788 .token
789 .try_safe_batch_transfer_from(
790 &env.alice,
791 &env.bob,
792 [U256::one(), U256::from(2)].to_vec(),
793 [50.into(), 300.into()].to_vec(),
794 &None
795 )
796 .unwrap_err();
797 assert_eq!(err, Error::InsufficientBalance.into());
798
799 let mut env = setup();
801
802 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
804 env.token
805 .mint(&env.alice, &U256::from(2), &200.into(), &None);
806 env.env.set_caller(env.bob);
808 let err = env
809 .token
810 .try_safe_batch_transfer_from(
811 &env.alice,
812 &env.bob,
813 [U256::one(), U256::from(2)].to_vec(),
814 [50.into(), 100.into()].to_vec(),
815 &None
816 )
817 .unwrap_err();
818 assert_eq!(err, Error::NotAnOwnerOrApproved.into());
819 }
820
821 #[test]
822 fn safe_transfer_to_valid_receiver() {
823 let mut env = setup();
825 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
828 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
830
831 env.env.set_caller(env.alice);
833 env.token.safe_transfer_from(
834 &env.alice,
835 &receiver.address(),
836 &U256::one(),
837 &100.into(),
838 &None
839 );
840
841 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
843 assert_eq!(
844 env.token.balance_of(&receiver.address(), &U256::one()),
845 100.into()
846 );
847
848 env.env.emitted_event(
850 &receiver,
851 SingleReceived {
852 operator: Some(env.alice),
853 from: Some(env.alice),
854 token_id: U256::one(),
855 amount: 100.into(),
856 data: None
857 }
858 );
859 }
860
861 #[test]
862 fn safe_transfer_to_valid_receiver_with_data() {
863 let mut env = setup();
865 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
867 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
869
870 env.env.set_caller(env.alice);
872 env.token.safe_transfer_from(
873 &env.alice,
874 &receiver.address(),
875 &U256::one(),
876 &100.into(),
877 &Some(Bytes::from(b"data".to_vec()))
878 );
879
880 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
882 assert_eq!(
883 env.token.balance_of(&receiver.address(), &U256::one()),
884 100.into()
885 );
886
887 env.env.emitted_event(
889 &receiver,
890 SingleReceived {
891 operator: Some(env.alice),
892 from: Some(env.alice),
893 token_id: U256::one(),
894 amount: 100.into(),
895 data: Some(Bytes::from(b"data".to_vec()))
896 }
897 );
898 }
899
900 #[test]
901 fn safe_transfer_to_invalid_receiver() {
902 let mut env = setup();
904 let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
906 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
908
909 env.env.set_caller(env.alice);
912 let err = env.token.try_safe_transfer_from(
913 &env.alice,
914 &receiver.address(),
915 &U256::one(),
916 &100.into(),
917 &None
918 );
919 assert_eq!(
920 err,
921 Err(OdraError::VmError(VmError::NoSuchMethod(
922 "on_erc1155_received".to_string()
923 )))
924 );
925 }
926
927 #[test]
928 fn safe_batch_transfer_to_valid_receiver() {
929 let mut env = setup();
931 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
933 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
935 env.token
936 .mint(&env.alice, &U256::from(2), &100.into(), &None);
937
938 env.env.set_caller(env.alice);
940 env.token.safe_batch_transfer_from(
941 &env.alice,
942 &receiver.address(),
943 [U256::one(), U256::from(2)].to_vec(),
944 [100.into(), 100.into()].to_vec(),
945 &None
946 );
947
948 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
950 assert_eq!(
951 env.token.balance_of(&receiver.address(), &U256::one()),
952 100.into()
953 );
954 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 0.into());
955 assert_eq!(
956 env.token.balance_of(&receiver.address(), &U256::from(2)),
957 100.into()
958 );
959
960 env.env.emitted_event(
962 &receiver,
963 BatchReceived {
964 operator: Some(env.alice),
965 from: Some(env.alice),
966 token_ids: [U256::one(), U256::from(2)].to_vec(),
967 amounts: [100.into(), 100.into()].to_vec(),
968 data: None
969 }
970 );
971 }
972
973 #[test]
974 fn safe_batch_transfer_to_valid_receiver_with_data() {
975 let mut env = setup();
977 let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
979 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
981 env.token
982 .mint(&env.alice, &U256::from(2), &100.into(), &None);
983
984 env.env.set_caller(env.alice);
986 env.token.safe_batch_transfer_from(
987 &env.alice,
988 &receiver.address(),
989 [U256::one(), U256::from(2)].to_vec(),
990 [100.into(), 100.into()].to_vec(),
991 &Some(Bytes::from(b"data".to_vec()))
992 );
993
994 assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 0.into());
996 assert_eq!(
997 env.token.balance_of(&receiver.address(), &U256::one()),
998 100.into()
999 );
1000 assert_eq!(env.token.balance_of(&env.alice, &U256::from(2)), 0.into());
1001 assert_eq!(
1002 env.token.balance_of(&receiver.address(), &U256::from(2)),
1003 100.into()
1004 );
1005
1006 env.env.emitted_event(
1008 &receiver,
1009 BatchReceived {
1010 operator: Some(env.alice),
1011 from: Some(env.alice),
1012 token_ids: [U256::one(), U256::from(2)].to_vec(),
1013 amounts: [100.into(), 100.into()].to_vec(),
1014 data: Some(Bytes::from(b"data".to_vec()))
1015 }
1016 );
1017 }
1018
1019 #[test]
1020 fn safe_batch_transfer_to_invalid_receiver() {
1021 let mut env = setup();
1023 let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
1025 env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
1027 env.token
1028 .mint(&env.alice, &U256::from(2), &100.into(), &None);
1029
1030 env.env.set_caller(env.alice);
1033 let err = env
1034 .token
1035 .try_safe_batch_transfer_from(
1036 &env.alice,
1037 &receiver.address(),
1038 vec![U256::one(), U256::from(2)],
1039 vec![100.into(), 100.into()],
1040 &None
1041 )
1042 .unwrap_err();
1043 assert_eq!(
1044 err,
1045 OdraError::VmError(VmError::NoSuchMethod(
1046 "on_erc1155_batch_received".to_string()
1047 ))
1048 );
1049 }
1050}