1use std::collections::BTreeMap;
2
3use crate::data;
4use crate::event::*;
5use alloc::string::String;
6use casper_erc20_crate::{Address, Error, ERC20 as CasperErc20};
7use casper_types::ContractHash;
8use casper_types::Key;
9use casper_types::{ContractPackageHash, U256};
10use casperlabs_contract_utils::{ContractContext, ContractStorage};
11use casperlabs_ownable::OWNABLE;
12use casper_contract::contract_api::storage;
13use casper_contract::contract_api::runtime;
14
15pub trait ERC20<Storage: ContractStorage>:
16 ContractContext<Storage> + OWNABLE<Storage> {
17 fn init(&mut self, contract_hash: ContractHash, package_hash: ContractPackageHash) {
18 OWNABLE::init(self, contract_hash, package_hash);
19 data::set_contract_hash(contract_hash);
20 data::set_package_hash(package_hash);
21 }
22
23 fn name(&self) -> String {
24 CasperErc20::default().name()
25 }
26
27 fn symbol(&self) -> String {
28 CasperErc20::default().symbol()
29 }
30
31 fn decimals(&self) -> u8 {
32 CasperErc20::default().decimals()
33 }
34
35 fn total_supply(&self) -> U256 {
36 CasperErc20::default().total_supply()
37 }
38
39 fn balance_of(&self, owner: Address) -> U256 {
40 CasperErc20::default().balance_of(owner)
41 }
42
43 fn allowance(&self, owner: Address, spender: Address) -> U256 {
44 CasperErc20::default().allowance(owner, spender)
45 }
46
47 fn increase_allowance(&self, spender: Address, amount: U256) -> Result<(), Error> {
48 CasperErc20::default().increase_allowance(spender, amount)
49 }
50
51 fn decrease_allowance(&self, spender: Address, amount: U256) -> Result<(), Error> {
52 CasperErc20::default().decrease_allowance(spender, amount)
53 }
54
55 fn transfer(&self, recipient: Address, amount: U256) -> Result<(), Error> {
56 let ret = CasperErc20::default().transfer(recipient, amount);
57 if ret.is_ok() {
58 emit(&ERC20Event::Transfer {
59 from: self.get_caller(),
60 to: Key::from(recipient),
61 value: amount,
62 });
63 }
64 ret
65 }
66
67 fn _approve(&self, owner: Address, spender: Address, value: U256) -> Result<(), Error> {
68 let ret = CasperErc20::default()._approve(owner, spender, value);
69 if ret.is_ok() {
70 emit(&ERC20Event::Approval {
71 owner: Key::from(owner),
72 spender: Key::from(spender),
73 value,
74 });
75 }
76 ret
77 }
78
79 fn approve(&self, spender: Address, value: U256) -> Result<(), Error> {
80 self._approve(Address::from(self.get_caller()), spender, value)
81 }
82
83 fn transfer_from(&self, from: Address, to: Address, value: U256) -> Result<(), Error> {
84 let ret = CasperErc20::default().transfer_from(from, to, value);
85 if ret.is_ok() {
86 emit(&ERC20Event::Transfer {
87 from: Key::from(from),
88 to: Key::from(to),
89 value,
90 });
91 }
92 ret
93 }
94
95 fn mint(&self, to: Address, value: U256) -> Result<(), Error> {
96 OWNABLE::only_owner(self);
97 let ret = CasperErc20::default().mint(to, value);
98 if ret.is_ok() {
99 emit(&ERC20Event::Transfer {
100 from: Key::from_formatted_str(
101 "hash-0000000000000000000000000000000000000000000000000000000000000000",
102 )
103 .unwrap(),
104 to: Key::from(to),
105 value,
106 });
107 }
108 ret
109 }
110
111 fn burn(&self, from: Address, value: U256) -> Result<(), Error> {
112 OWNABLE::only_owner(self);
113 let ret = CasperErc20::default().burn(from, value);
114 if ret.is_ok() {
115 emit(&ERC20Event::Transfer {
116 from: Key::from(from),
117 to: Key::from_formatted_str(
118 "hash-0000000000000000000000000000000000000000000000000000000000000000",
119 )
120 .unwrap(),
121 value,
122 });
123 }
124 ret
125 }
126
127 fn named_keys(
128 &self,
129 name: String,
130 symbol: String,
131 decimals: u8,
132 initial_supply: U256,
133 package_hash: ContractPackageHash,
134 ) -> Result<BTreeMap<String, Key>, Error> {
135 let ret = CasperErc20::default().named_keys(name, symbol, decimals, initial_supply);
136 if ret.is_ok() {
137 let mut event = BTreeMap::new();
138 event.insert("contract_package_hash", package_hash.to_string());
139 event.insert("event_type", "transfer".to_string());
140 event.insert("from", data::zero_address().to_string());
141 event.insert("to", Key::from(runtime::get_caller()).to_string());
142 event.insert("value", initial_supply.to_string());
143 storage::new_uref(event);
144 }
145 ret
146 }
147}