1use crate::errors::PSP22Error;
2use crate::events::{Approval, Transfer};
3use ink::prelude::string::String;
4use ink::{
5 prelude::{vec, vec::Vec},
6 primitives::AccountId,
7 storage::Mapping,
8};
9
10pub enum PSP22Event {
13 Transfer(Transfer),
14 Approval(Approval),
15}
16
17fn approval_event(owner: AccountId, spender: AccountId, amount: u128) -> PSP22Event {
19 PSP22Event::Approval(Approval {
20 owner,
21 spender,
22 amount,
23 })
24}
25
26fn transfer_event(from: Option<AccountId>, to: Option<AccountId>, value: u128) -> PSP22Event {
28 PSP22Event::Transfer(Transfer { from, to, value })
29}
30
31#[ink::storage_item]
44#[derive(Debug, Default)]
45pub struct PSP22Data {
46 total_supply: u128,
47 balances: Mapping<AccountId, u128>,
48 allowances: Mapping<(AccountId, AccountId), u128>,
49}
50
51impl PSP22Data {
52 pub fn new(supply: u128, creator: AccountId) -> (PSP22Data, Vec<PSP22Event>) {
54 let mut data: PSP22Data = Default::default();
55 let events = data.mint(creator, supply).unwrap();
56 (data, events)
57 }
58
59 pub fn total_supply(&self) -> u128 {
60 self.total_supply
61 }
62
63 pub fn balance_of(&self, owner: AccountId) -> u128 {
64 self.balances.get(owner).unwrap_or_default()
65 }
66
67 pub fn allowance(&self, owner: AccountId, spender: AccountId) -> u128 {
68 self.allowances.get((owner, spender)).unwrap_or_default()
69 }
70
71 pub fn transfer(
73 &mut self,
74 caller: AccountId,
75 to: AccountId,
76 value: u128,
77 ) -> Result<Vec<PSP22Event>, PSP22Error> {
78 if caller == to || value == 0 {
79 return Ok(vec![]);
80 }
81 let from_balance = self.balance_of(caller);
82 if from_balance < value {
83 return Err(PSP22Error::InsufficientBalance);
84 }
85
86 if from_balance == value {
87 self.balances.remove(caller);
88 } else {
89 self.balances
90 .insert(caller, &(from_balance.saturating_sub(value)));
91 }
92 let to_balance = self.balance_of(to);
93 self.balances
95 .insert(to, &(to_balance.saturating_add(value)));
96 Ok(vec![transfer_event(Some(caller), Some(to), value)])
97 }
98
99 pub fn transfer_from(
102 &mut self,
103 caller: AccountId,
104 from: AccountId,
105 to: AccountId,
106 value: u128,
107 ) -> Result<Vec<PSP22Event>, PSP22Error> {
108 if from == to || value == 0 {
109 return Ok(vec![]);
110 }
111 if caller == from {
112 return self.transfer(caller, to, value);
113 }
114
115 let allowance = self.allowance(from, caller);
116 if allowance < value {
117 return Err(PSP22Error::InsufficientAllowance);
118 }
119 let from_balance = self.balance_of(from);
120 if from_balance < value {
121 return Err(PSP22Error::InsufficientBalance);
122 }
123
124 if allowance == value {
125 self.allowances.remove((from, caller));
126 } else {
127 self.allowances
128 .insert((from, caller), &(allowance.saturating_sub(value)));
129 }
130
131 if from_balance == value {
132 self.balances.remove(from);
133 } else {
134 self.balances
135 .insert(from, &(from_balance.saturating_sub(value)));
136 }
137 let to_balance = self.balance_of(to);
138 self.balances
140 .insert(to, &(to_balance.saturating_add(value)));
141 Ok(vec![
142 approval_event(from, caller, allowance.saturating_sub(value)),
143 transfer_event(Some(from), Some(to), value),
144 ])
145 }
146
147 pub fn approve(
150 &mut self,
151 owner: AccountId,
152 spender: AccountId,
153 value: u128,
154 ) -> Result<Vec<PSP22Event>, PSP22Error> {
155 if owner == spender {
156 return Ok(vec![]);
157 }
158 if value == 0 {
159 self.allowances.remove((owner, spender));
160 } else {
161 self.allowances.insert((owner, spender), &value);
162 }
163 Ok(vec![approval_event(owner, spender, value)])
164 }
165
166 pub fn increase_allowance(
168 &mut self,
169 owner: AccountId,
170 spender: AccountId,
171 delta_value: u128,
172 ) -> Result<Vec<PSP22Event>, PSP22Error> {
173 if owner == spender || delta_value == 0 {
174 return Ok(vec![]);
175 }
176 let allowance = self.allowance(owner, spender);
177 let amount = allowance.saturating_add(delta_value);
178 self.allowances.insert((owner, spender), &amount);
179 Ok(vec![approval_event(owner, spender, amount)])
180 }
181
182 pub fn decrease_allowance(
184 &mut self,
185 owner: AccountId,
186 spender: AccountId,
187 delta_value: u128,
188 ) -> Result<Vec<PSP22Event>, PSP22Error> {
189 if owner == spender || delta_value == 0 {
190 return Ok(vec![]);
191 }
192 let allowance = self.allowance(owner, spender);
193 if allowance < delta_value {
194 return Err(PSP22Error::InsufficientAllowance);
195 }
196 let amount = allowance.saturating_sub(delta_value);
197 if amount == 0 {
198 self.allowances.remove((owner, spender));
199 } else {
200 self.allowances.insert((owner, spender), &amount);
201 }
202 Ok(vec![approval_event(owner, spender, amount)])
203 }
204
205 pub fn mint(&mut self, to: AccountId, value: u128) -> Result<Vec<PSP22Event>, PSP22Error> {
207 if value == 0 {
208 return Ok(vec![]);
209 }
210 let new_supply = self
211 .total_supply
212 .checked_add(value)
213 .ok_or(PSP22Error::Custom(String::from(
214 "Max PSP22 supply exceeded. Max supply limited to 2^128-1.",
215 )))?;
216 self.total_supply = new_supply;
217 let new_balance = self.balance_of(to).saturating_add(value);
218 self.balances.insert(to, &new_balance);
219 Ok(vec![transfer_event(None, Some(to), value)])
220 }
221
222 pub fn burn(&mut self, from: AccountId, value: u128) -> Result<Vec<PSP22Event>, PSP22Error> {
224 if value == 0 {
225 return Ok(vec![]);
226 }
227 let balance = self.balance_of(from);
228 if balance < value {
229 return Err(PSP22Error::InsufficientBalance);
230 }
231 if balance == value {
232 self.balances.remove(from);
233 } else {
234 self.balances.insert(from, &(balance.saturating_sub(value)));
235 }
236 self.total_supply = self.total_supply.saturating_sub(value);
237 Ok(vec![transfer_event(Some(from), None, value)])
238 }
239}