odra_modules/
erc1155_token.rs

1//! A pluggable Odra module implementing Erc1155 token with ownership.
2use 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/// The ERC1155 token implementation.
12/// It uses the [ERC1155](Erc1155Base) base implementation and the [Ownable] module.
13#[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    // Ownable
61    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        // Given a deployed contract
221        let mut env = setup();
222
223        // When we mint some tokens
224        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
225
226        // Then the balance is updated
227        assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
228
229        // And the event is emitted
230        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        // Given a deployed contract
246        let mut env = setup();
247
248        // When we mint some tokens in batch
249        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        // Then it emits the event
257        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        // And the balances are updated
269        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        // Given a deployed contract
276        let mut env = setup();
277        // When we mint some tokens in batch with mismatching ids and amounts it errors out
278        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        // Given a deployed contract
293        let mut env = setup();
294
295        // And some tokens minted
296        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
297
298        // When we burn some tokens
299        env.token.burn(&env.alice, &U256::one(), &50.into());
300
301        // Then the balance is updated
302        assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
303
304        // And the event is emitted
305        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        // Given a deployed contract
321        let mut env = setup();
322
323        // And some tokens minted
324        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
325        // When we burn more tokens than we have it errors out
326        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        // Given a deployed contract
333        let mut env = setup();
334        // When we burn non-existing tokens it errors out
335        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        // Given a deployed contract
345        let mut env = setup();
346
347        // And some tokens minted
348        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        // When we burn some tokens in batch
356        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        // Then the balances are updated
363        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        // And the event is emitted
367        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        // Given a deployed contract
383        let mut env = setup();
384
385        // And some tokens minted
386        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        // When we burn some tokens in batch with mismatching ids and amounts it errors out
394        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        // Given a deployed contract
405        let mut env = setup();
406
407        // And some tokens minted
408        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        // When we burn more tokens than we have it errors out
416        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        // Given a deployed contract
427        let mut env = setup();
428
429        // When we burn non-existing tokens it errors out
430        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        // Given a deployed contract
444        let mut env = setup();
445
446        // And some tokens minted
447        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        // Then it returns the correct balance
453        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        // Given a deployed contract
462        let mut env = setup();
463
464        // And some tokens minted
465        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        // Then it returns the correct balances
479        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            // TODO: Why it gives deserialization error when mismatched?
493            [
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        // Given a deployed contract
508        let mut env = setup();
509
510        // And some tokens minted
511        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        // When we query balances with mismatching ids and addresses it errors out
519        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        // Given a deployed contract
532        let mut env = setup();
533
534        // When we set approval for all
535        env.env.set_caller(env.alice);
536        env.token.set_approval_for_all(&env.bob, true);
537
538        // Then the approval is set
539        assert!(env.token.is_approved_for_all(&env.alice, &env.bob));
540
541        // And the event is emitted
542        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        // Given a deployed contract
555        let mut env = setup();
556
557        // And approval for all set
558        env.env.set_caller(env.alice);
559        env.token.set_approval_for_all(&env.bob, true);
560
561        // When we unset approval for all
562        env.env.set_caller(env.alice);
563        env.token.set_approval_for_all(&env.bob, false);
564
565        // Then the approval is unset
566        assert!(!env.token.is_approved_for_all(&env.alice, &env.bob));
567
568        // And the event is emitted
569        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        // Given a deployed contract
583        let mut env = setup();
584
585        // Then approving for self throws an error
586        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        // Given a deployed contract
597        let mut env = setup();
598
599        // And some tokens minted
600        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
601
602        // When we transfer tokens
603        env.env.set_caller(env.alice);
604        env.token
605            .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
606
607        // Then the tokens are transferred
608        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        // And the event is emitted
612        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        // Given a deployed contract
628        let mut env = setup();
629
630        // And some tokens minted
631        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
632
633        // And approval for all set
634        env.env.set_caller(env.alice);
635        env.token.set_approval_for_all(&env.bob, true);
636
637        // When we transfer tokens
638        env.env.set_caller(env.bob);
639        env.token
640            .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
641
642        // Then the tokens are transferred
643        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        // And the event is emitted
647        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        // Given a deployed contract
663        let mut env = setup();
664
665        // And some tokens minted
666        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
667
668        // When we transfer more tokens than we have it errors out
669        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        // Given a deployed contract
677        // env.env.set_caller(test_env::get_account(0));
678        let mut env = setup();
679        // And some tokens minted
680        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
681
682        // When we transfer not our tokens it errors out
683        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        // Given a deployed contract
694        let mut env = setup();
695
696        // And some tokens minted
697        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        // When we transfer tokens
702        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        // Then the tokens are transferred
712        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        // And the event is emitted
718        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        // Given a deployed contract
734        let mut env = setup();
735
736        // And some tokens minted
737        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        // And approval for all set
742        env.env.set_caller(env.alice);
743        env.token.set_approval_for_all(&env.bob, true);
744
745        // When we transfer tokens
746        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        // Then the tokens are transferred
756        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        // And the event is emitted
762        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        // Given a deployed contract
778        let mut env = setup();
779
780        // And some tokens minted
781        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
782        env.token
783            .mint(&env.alice, &U256::from(2), &200.into(), &None);
784        // When we transfer more tokens than we have it errors out
785        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        // Given a deployed contract
799        let mut env = setup();
800
801        // And some tokens minted
802        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
803        env.token
804            .mint(&env.alice, &U256::from(2), &200.into(), &None);
805        // When we transfer not our tokens it errors out
806        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        // Given a deployed contract
823        let mut env = setup();
824        // And a valid receiver
825
826        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
827        // And some tokens minted
828        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
829
830        // When we transfer tokens to a valid receiver
831        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        // Then the tokens are transferred
841        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        // And receiver contract is aware of received tokens
848        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        // Given a deployed contract
863        let mut env = setup();
864        // And a valid receiver
865        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
866        // And some tokens minted
867        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
868
869        // When we transfer tokens to a valid receiver
870        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        // Then the tokens are transferred
880        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        // And receiver contract is aware of received tokens and data
887        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        // Given a deployed contract
902        let mut env = setup();
903        // And an invalid receiver
904        let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
905        // And some tokens minted
906        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
907
908        // When we transfer tokens to an invalid receiver
909        // Then it errors out
910        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        // Given a deployed contract
929        let mut env = setup();
930        // And a valid receiver
931        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
932        // And some tokens minted
933        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        // When we transfer tokens to a valid receiver
938        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        // Then the tokens are transferred
948        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        // And receiver contract is aware of received tokens
960        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        // Given a deployed contract
975        let mut env = setup();
976        // And a valid receiver
977        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
978        // And some tokens minted
979        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        // When we transfer tokens to a valid receiver
984        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        // Then the tokens are transferred
994        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        // And receiver contract is aware of received tokens and data
1006        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        // Given a deployed contract
1021        let mut env = setup();
1022        // And an invalid receiver
1023        let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
1024        // And some tokens minted
1025        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        // When we transfer tokens to an invalid receiver
1030        // Then it errors out
1031        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}