odra_modules/erc721/
erc721_base.rs

1//! Odra module implementing Erc721 core.
2use crate::erc721::errors::Error;
3use crate::erc721::events::{Approval, ApprovalForAll, Transfer};
4use crate::erc721::extensions::erc721_receiver::Erc721Receiver;
5use crate::erc721::Erc721;
6use crate::erc721_receiver::Erc721ReceiverContractRef;
7use odra::casper_types::{bytesrepr::Bytes, U256};
8use odra::prelude::*;
9use odra::ContractRef;
10/// The ERC721 base implementation.
11#[odra::module(events = [Approval, ApprovalForAll, Transfer], errors = Error)]
12pub struct Erc721Base {
13    /// The token balances.
14    pub balances: Mapping<Address, U256>,
15    /// The token owners.
16    pub owners: Mapping<U256, Option<Address>>,
17    /// The token approvals.
18    pub token_approvals: Mapping<U256, Option<Address>>,
19    /// The operator approvals.
20    pub operator_approvals: Mapping<(Address, Address), bool>
21}
22
23impl Erc721 for Erc721Base {
24    fn balance_of(&self, owner: &Address) -> U256 {
25        self.balances.get_or_default(owner)
26    }
27
28    fn owner_of(&self, token_id: &U256) -> Address {
29        self.owners
30            .get(token_id)
31            .unwrap_or_revert_with(&self.env(), Error::InvalidTokenId)
32            .unwrap_or_revert_with(&self.env(), Error::InvalidTokenId)
33    }
34
35    fn safe_transfer_from(&mut self, from: &Address, to: &Address, token_id: &U256) {
36        if !self.is_approved_or_owner(&self.env().caller(), token_id) {
37            self.env().revert(Error::NotAnOwnerOrApproved);
38        }
39        self.safe_transfer(from, to, token_id, &None);
40    }
41
42    fn safe_transfer_from_with_data(
43        &mut self,
44        from: &Address,
45        to: &Address,
46        token_id: &U256,
47        data: &Bytes
48    ) {
49        if !self.is_approved_or_owner(&self.env().caller(), token_id) {
50            self.env().revert(Error::NotAnOwnerOrApproved);
51        }
52        self.safe_transfer(from, to, token_id, &Some(data.clone()));
53    }
54
55    fn transfer_from(&mut self, from: &Address, to: &Address, token_id: &U256) {
56        if !self.is_approved_or_owner(&self.env().caller(), token_id) {
57            self.env().revert(Error::NotAnOwnerOrApproved);
58        }
59        self.transfer(from, to, token_id);
60    }
61
62    fn approve(&mut self, approved: &Option<Address>, token_id: &U256) {
63        let owner = self.owner_of(token_id);
64        let caller = self.env().caller();
65
66        if &Some(owner) == approved {
67            self.env().revert(Error::ApprovalToCurrentOwner);
68        }
69
70        if caller != owner && !self.is_approved_for_all(&owner, &caller) {
71            self.env().revert(Error::NotAnOwnerOrApproved);
72        }
73
74        self.token_approvals.set(token_id, *approved);
75
76        self.env().emit_event(Approval {
77            owner,
78            approved: *approved,
79            token_id: *token_id
80        });
81    }
82
83    fn set_approval_for_all(&mut self, operator: &Address, approved: bool) {
84        let caller = self.env().caller();
85        if &caller == operator {
86            self.env().revert(Error::ApproveToCaller)
87        }
88
89        self.operator_approvals.set(&(caller, *operator), approved);
90        self.env().emit_event(ApprovalForAll {
91            owner: caller,
92            operator: *operator,
93            approved
94        });
95    }
96
97    fn get_approved(&self, token_id: &U256) -> Option<Address> {
98        self.assert_exists(token_id);
99        self.token_approvals.get(token_id).unwrap_or_default()
100    }
101
102    fn is_approved_for_all(&self, owner: &Address, operator: &Address) -> bool {
103        self.operator_approvals
104            .get(&(*owner, *operator))
105            .unwrap_or_default()
106    }
107}
108
109impl Erc721Base {
110    /// Returns true if the `spender` is the owner or an operator of the `token_id` token.
111    pub fn is_approved_or_owner(&self, spender: &Address, token_id: &U256) -> bool {
112        let owner = &self.owner_of(token_id);
113        (spender == owner)
114            || self.get_approved(token_id) == Some(*spender)
115            || self.is_approved_for_all(owner, spender)
116    }
117
118    fn safe_transfer(
119        &mut self,
120        from: &Address,
121        to: &Address,
122        token_id: &U256,
123        data: &Option<Bytes>
124    ) {
125        self.transfer(from, to, token_id);
126        if to.is_contract() {
127            let response = Erc721ReceiverContractRef::new(self.env(), *to).on_erc721_received(
128                &self.env().caller(),
129                from,
130                token_id,
131                data
132            );
133
134            if !response {
135                self.env().revert(Error::TransferFailed)
136            }
137        }
138    }
139
140    /// Transfers the `token_id` token from `from` to `to`.
141    pub fn transfer(&mut self, from: &Address, to: &Address, token_id: &U256) {
142        self.clear_approval(token_id);
143        self.balances.set(from, self.balance_of(from) - 1);
144        self.balances.set(to, self.balance_of(to) + 1);
145        self.owners.set(token_id, Some(*to));
146
147        self.env().emit_event(Transfer {
148            from: Some(*from),
149            to: Some(*to),
150            token_id: *token_id
151        });
152    }
153
154    /// Revokes permission to transfer the `token_id` token.
155    pub fn clear_approval(&mut self, token_id: &U256) {
156        if self.token_approvals.get_or_default(token_id).is_some() {
157            self.token_approvals.set(token_id, None);
158        }
159    }
160
161    /// Returns true if the `token_id` token exists.
162    pub fn exists(&self, token_id: &U256) -> bool {
163        self.owners.get(token_id).is_some()
164    }
165
166    /// Reverts with [Error::InvalidTokenId] if the `token_id` token does not exist.
167    pub fn assert_exists(&self, token_id: &U256) {
168        if !self.exists(token_id) {
169            self.env().revert(Error::InvalidTokenId);
170        }
171    }
172}