-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
158 lines (145 loc) · 5.39 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#![cfg_attr(not(feature = "std"), no_std, no_main)]
pub use self::button::ButtonRef;
#[openbrush::implementation(PSP22, PSP22Metadata, PSP22Capped)]
#[openbrush::contract]
pub mod button {
use ink::codegen::{EmitEvent, Env};
use openbrush::traits::Storage;
// === EVENTS ===
/// Event emitted when a token transfer occurs.
#[ink(event)]
pub struct Transfer {
#[ink(topic)]
from: Option<AccountId>,
#[ink(topic)]
to: Option<AccountId>,
value: Balance,
}
/// Event emitted when an approval occurs that `spender` is allowed to withdraw
/// up to the amount of `value` tokens from `owner`.
#[ink(event)]
pub struct Approval {
#[ink(topic)]
owner: AccountId,
#[ink(topic)]
spender: AccountId,
value: Balance,
}
// === STRUCTS ===
#[ink(storage)]
#[derive(Default, Storage)]
pub struct Button {
#[storage_field]
psp22: psp22::Data,
#[storage_field]
metadata: metadata::Data,
#[storage_field]
cap: capped::Data,
}
#[overrider(psp22::Internal)]
fn _emit_transfer_event(
&self,
from: Option<AccountId>,
to: Option<AccountId>,
amount: Balance,
) {
self.env().emit_event(Transfer {
from,
to,
value: amount,
});
}
#[overrider(psp22::Internal)]
fn _emit_approval_event(&self, owner: AccountId, spender: AccountId, amount: Balance) {
self.env().emit_event(Approval {
owner,
spender,
value: amount,
});
}
impl Button {
#[ink(constructor)]
pub fn new(
cap: Balance,
name: Option<String>,
symbol: Option<String>,
decimal: u8,
) -> Self {
let mut instance = Self::default();
assert!(capped::Internal::_init_cap(&mut instance, cap).is_ok());
assert!(psp22::Internal::_mint_to(&mut instance, Self::env().caller(), cap).is_ok());
instance.metadata.name.set(&name);
instance.metadata.symbol.set(&symbol);
instance.metadata.decimals.set(&decimal);
instance
}
#[ink(message)]
pub fn burn(&mut self, account: AccountId, amount: Balance) -> Result<(), PSP22Error> {
let caller = Self::env().caller();
if caller != account {
let allowance: Balance = psp22::Internal::_allowance(self, &account, &caller);
if allowance < amount {
return Err(PSP22Error::InsufficientAllowance);
}
psp22::Internal::_approve_from_to(self, account, caller, allowance - amount)?;
}
psp22::Internal::_burn_from(self, account, amount)
}
}
#[cfg(test)]
mod tests {
use super::*;
use ink::env::{
test::{default_accounts, set_caller, DefaultAccounts},
DefaultEnvironment,
};
// === HELPERS ===
fn init() -> (DefaultAccounts<DefaultEnvironment>, Button) {
let accounts = default_accounts();
set_caller::<DefaultEnvironment>(accounts.bob);
let az_button = Button::new(
28_000_000_000_000,
Some("Button".to_string()),
Some("BTN".to_string()),
6,
);
(accounts, az_button)
}
// === TEST HANDLES ===
#[ink::test]
fn test_burn() {
let (accounts, mut az_button) = init();
// when burning from own account
// = when balance is sufficient
// = * it burns the amount
az_button.burn(accounts.bob, 1_000_000_000_000).unwrap();
let mut balance: Balance = PSP22::balance_of(&az_button, accounts.bob);
assert_eq!(balance, 27_000_000_000_000);
// = when balance is insufficient
let mut result = az_button.burn(accounts.bob, 28_000_000_000_000);
// = * it raises an error
assert_eq!(result, Err(PSP22Error::InsufficientBalance));
// when burning from someone else's account
// = when balance is sufficient
// == when allowance is insufficient
set_caller::<DefaultEnvironment>(accounts.alice);
// == * it raises an error
result = az_button.burn(accounts.bob, 27_000_000_000_000);
assert_eq!(result, Err(PSP22Error::InsufficientAllowance));
// == when allowance is sufficient
set_caller::<DefaultEnvironment>(accounts.bob);
PSP22::increase_allowance(&mut az_button, accounts.alice, 28_000_000_000_000).unwrap();
set_caller::<DefaultEnvironment>(accounts.alice);
az_button.burn(accounts.bob, 1_000_000_000_000).unwrap();
// == * it burns the amount
balance = PSP22::balance_of(&az_button, accounts.bob);
assert_eq!(balance, 26_000_000_000_000);
// == * it decreases the allowance
let allowance: Balance = PSP22::allowance(&az_button, accounts.bob, accounts.alice);
assert_eq!(allowance, 27_000_000_000_000);
// === when balance is insufficient
result = az_button.burn(accounts.bob, 27_000_000_000_000);
assert_eq!(result, Err(PSP22Error::InsufficientBalance));
}
}
}