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        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    // Ownable
62    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        // Given a deployed contract
222        let mut env = setup();
223
224        // When we mint some tokens
225        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
226
227        // Then the balance is updated
228        assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 100.into());
229
230        // And the event is emitted
231        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        // Given a deployed contract
247        let mut env = setup();
248
249        // When we mint some tokens in batch
250        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        // Then it emits the event
258        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        // And the balances are updated
270        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        // Given a deployed contract
277        let mut env = setup();
278        // When we mint some tokens in batch with mismatching ids and amounts it errors out
279        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        // Given a deployed contract
294        let mut env = setup();
295
296        // And some tokens minted
297        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
298
299        // When we burn some tokens
300        env.token.burn(&env.alice, &U256::one(), &50.into());
301
302        // Then the balance is updated
303        assert_eq!(env.token.balance_of(&env.alice, &U256::one()), 50.into());
304
305        // And the event is emitted
306        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        // Given a deployed contract
322        let mut env = setup();
323
324        // And some tokens minted
325        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
326        // When we burn more tokens than we have it errors out
327        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        // Given a deployed contract
334        let mut env = setup();
335        // When we burn non-existing tokens it errors out
336        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        // Given a deployed contract
346        let mut env = setup();
347
348        // And some tokens minted
349        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        // When we burn some tokens in batch
357        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        // Then the balances are updated
364        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        // And the event is emitted
368        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        // Given a deployed contract
384        let mut env = setup();
385
386        // And some tokens minted
387        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        // When we burn some tokens in batch with mismatching ids and amounts it errors out
395        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        // Given a deployed contract
406        let mut env = setup();
407
408        // And some tokens minted
409        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        // When we burn more tokens than we have it errors out
417        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        // Given a deployed contract
428        let mut env = setup();
429
430        // When we burn non-existing tokens it errors out
431        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        // Given a deployed contract
445        let mut env = setup();
446
447        // And some tokens minted
448        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        // Then it returns the correct balance
454        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        // Given a deployed contract
463        let mut env = setup();
464
465        // And some tokens minted
466        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        // Then it returns the correct balances
480        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            // TODO: Why it gives deserialization error when mismatched?
494            [
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        // Given a deployed contract
509        let mut env = setup();
510
511        // And some tokens minted
512        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        // When we query balances with mismatching ids and addresses it errors out
520        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        // Given a deployed contract
533        let mut env = setup();
534
535        // When we set approval for all
536        env.env.set_caller(env.alice);
537        env.token.set_approval_for_all(&env.bob, true);
538
539        // Then the approval is set
540        assert!(env.token.is_approved_for_all(&env.alice, &env.bob));
541
542        // And the event is emitted
543        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        // Given a deployed contract
556        let mut env = setup();
557
558        // And approval for all set
559        env.env.set_caller(env.alice);
560        env.token.set_approval_for_all(&env.bob, true);
561
562        // When we unset approval for all
563        env.env.set_caller(env.alice);
564        env.token.set_approval_for_all(&env.bob, false);
565
566        // Then the approval is unset
567        assert!(!env.token.is_approved_for_all(&env.alice, &env.bob));
568
569        // And the event is emitted
570        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        // Given a deployed contract
584        let mut env = setup();
585
586        // Then approving for self throws an error
587        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        // Given a deployed contract
598        let mut env = setup();
599
600        // And some tokens minted
601        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
602
603        // When we transfer tokens
604        env.env.set_caller(env.alice);
605        env.token
606            .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
607
608        // Then the tokens are transferred
609        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        // And the event is emitted
613        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        // Given a deployed contract
629        let mut env = setup();
630
631        // And some tokens minted
632        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
633
634        // And approval for all set
635        env.env.set_caller(env.alice);
636        env.token.set_approval_for_all(&env.bob, true);
637
638        // When we transfer tokens
639        env.env.set_caller(env.bob);
640        env.token
641            .safe_transfer_from(&env.alice, &env.bob, &U256::one(), &50.into(), &None);
642
643        // Then the tokens are transferred
644        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        // And the event is emitted
648        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        // Given a deployed contract
664        let mut env = setup();
665
666        // And some tokens minted
667        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
668
669        // When we transfer more tokens than we have it errors out
670        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        // Given a deployed contract
678        // env.env.set_caller(test_env::get_account(0));
679        let mut env = setup();
680        // And some tokens minted
681        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
682
683        // When we transfer not our tokens it errors out
684        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        // Given a deployed contract
695        let mut env = setup();
696
697        // And some tokens minted
698        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        // When we transfer tokens
703        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        // Then the tokens are transferred
713        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        // And the event is emitted
719        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        // Given a deployed contract
735        let mut env = setup();
736
737        // And some tokens minted
738        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        // And approval for all set
743        env.env.set_caller(env.alice);
744        env.token.set_approval_for_all(&env.bob, true);
745
746        // When we transfer tokens
747        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        // Then the tokens are transferred
757        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        // And the event is emitted
763        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        // Given a deployed contract
779        let mut env = setup();
780
781        // And some tokens minted
782        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
783        env.token
784            .mint(&env.alice, &U256::from(2), &200.into(), &None);
785        // When we transfer more tokens than we have it errors out
786        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        // Given a deployed contract
800        let mut env = setup();
801
802        // And some tokens minted
803        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
804        env.token
805            .mint(&env.alice, &U256::from(2), &200.into(), &None);
806        // When we transfer not our tokens it errors out
807        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        // Given a deployed contract
824        let mut env = setup();
825        // And a valid receiver
826
827        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
828        // And some tokens minted
829        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
830
831        // When we transfer tokens to a valid receiver
832        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        // Then the tokens are transferred
842        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        // And receiver contract is aware of received tokens
849        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        // Given a deployed contract
864        let mut env = setup();
865        // And a valid receiver
866        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
867        // And some tokens minted
868        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
869
870        // When we transfer tokens to a valid receiver
871        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        // Then the tokens are transferred
881        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        // And receiver contract is aware of received tokens and data
888        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        // Given a deployed contract
903        let mut env = setup();
904        // And an invalid receiver
905        let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
906        // And some tokens minted
907        env.token.mint(&env.alice, &U256::one(), &100.into(), &None);
908
909        // When we transfer tokens to an invalid receiver
910        // Then it errors out
911        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        // Given a deployed contract
930        let mut env = setup();
931        // And a valid receiver
932        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
933        // And some tokens minted
934        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        // When we transfer tokens to a valid receiver
939        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        // Then the tokens are transferred
949        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        // And receiver contract is aware of received tokens
961        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        // Given a deployed contract
976        let mut env = setup();
977        // And a valid receiver
978        let receiver = Erc1155Receiver::deploy(&env.env, NoArgs);
979        // And some tokens minted
980        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        // When we transfer tokens to a valid receiver
985        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        // Then the tokens are transferred
995        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        // And receiver contract is aware of received tokens and data
1007        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        // Given a deployed contract
1022        let mut env = setup();
1023        // And an invalid receiver
1024        let receiver = WrappedNativeToken::deploy(&env.env, NoArgs);
1025        // And some tokens minted
1026        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        // When we transfer tokens to an invalid receiver
1031        // Then it errors out
1032        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}