odra_modules/erc721/
erc721_base.rs1use 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#[odra::module(events = [Approval, ApprovalForAll, Transfer], errors = Error)]
12pub struct Erc721Base {
13 pub balances: Mapping<Address, U256>,
15 pub owners: Mapping<U256, Option<Address>>,
17 pub token_approvals: Mapping<U256, Option<Address>>,
19 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 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 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 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 pub fn exists(&self, token_id: &U256) -> bool {
163 self.owners.get(token_id).is_some()
164 }
165
166 pub fn assert_exists(&self, token_id: &U256) {
168 if !self.exists(token_id) {
169 self.env().revert(Error::InvalidTokenId);
170 }
171 }
172}