1
+ use starknet :: ContractAddress ;
2
+
3
+ trait IERC20 {
4
+ fn name () -> felt252 ;
5
+ fn symbol () -> felt252 ;
6
+ fn decimals () -> u8 ;
7
+ fn total_supply () -> u256 ;
8
+ fn balanceOf (account : ContractAddress ) -> u256 ;
9
+ fn allowance (owner : ContractAddress , spender : ContractAddress ) -> u256 ;
10
+ fn transfer (recipient : ContractAddress , amount : u256 ) -> bool ;
11
+ fn transferFrom (sender : ContractAddress , recipient : ContractAddress , amount : u256 ) -> bool ;
12
+ fn approve (spender : ContractAddress , amount : u256 ) -> bool ;
13
+ }
14
+
1
15
#[contract]
2
- mod ERC20Contract {
3
- /// /////////////////////////////
4
- // library imports
5
- /// /////////////////////////////
6
- use zeroable :: Zeroable ;
16
+ mod ERC20 {
7
17
use starknet :: get_caller_address;
8
18
use starknet :: ContractAddress ;
9
- use starknet :: contract_address_try_from_felt252 ;
10
- use traits :: Into ;
11
- use traits :: TryInto ;
12
- use option :: OptionTrait ;
13
-
14
- /// /////////////////////////////
15
- // storage variables
16
- /// /////////////////////////////
19
+ use zeroable :: Zeroable ;
20
+ use super :: IERC20 ;
21
+
17
22
struct Storage {
18
- name : felt252 ,
19
- symbol : felt252 ,
20
- decimals : u8 ,
21
- total_supply : u256 ,
22
- balances : LegacyMap :: <ContractAddress , u256 >,
23
- allowances : LegacyMap :: <(ContractAddress , ContractAddress ), u256 >,
23
+ _name : felt252 ,
24
+ _symbol : felt252 ,
25
+ _decimals : u8 ,
26
+ _total_supply : u256 ,
27
+ _balances : LegacyMap <ContractAddress , u256 >,
28
+ _allowances : LegacyMap <(ContractAddress , ContractAddress ), u256 >,
24
29
}
25
30
26
- /// /////////////////////////////
27
- // Transfer event emitted on token transfer
28
- /// /////////////////////////////
29
31
#[event]
30
32
fn Transfer (from : ContractAddress , to : ContractAddress , value : u256 ) {}
31
33
32
- /// /////////////////////////////
33
- // Approval event emitted on token approval
34
- /// /////////////////////////////
35
34
#[event]
36
35
fn Approval (owner : ContractAddress , spender : ContractAddress , value : u256 ) {}
37
36
38
- /// /////////////////////////////
39
- // Constructor - initialized on deployment
40
- /// /////////////////////////////
41
37
#[constructor]
42
- fn constructor (
43
- name_ : felt252 ,
44
- symbol_ : felt252 ,
45
- decimals_ : u8 ,
46
- initial_supply : u256 ,
47
- recipient : ContractAddress
48
- ){
49
- name :: write (name_ );
50
- symbol :: write (symbol_ );
51
- decimals :: write (decimals_ );
52
- assert (recipient . is_non_zero (), ' ERC20: mint to the 0 address' );
53
- total_supply :: write (initial_supply );
54
- balances :: write (recipient , initial_supply );
55
- Transfer (Zeroable :: zero (), recipient , initial_supply );
38
+ fn constructor (name : felt252 , symbol : felt252 , decimals : u8 ) {
39
+ _name :: write (name );
40
+ _symbol :: write (symbol );
41
+ _decimals :: write (decimals );
56
42
}
57
43
58
- /// /////////////////////////////
59
- // get_name function returns token name
60
- /// /////////////////////////////
61
44
#[view]
62
- fn get_name () -> felt252 {
63
- name :: read ()
45
+ fn name () -> felt252 {
46
+ _name :: read ()
64
47
}
65
48
66
- /// /////////////////////////////
67
- // get_symbol function returns token symbol
68
- /// /////////////////////////////
69
49
#[view]
70
- fn get_symbol () -> felt252 {
71
- symbol :: read ()
50
+ fn symbol () -> felt252 {
51
+ _symbol :: read ()
72
52
}
73
53
74
- /// /////////////////////////////
75
- // get_decimals function returns token decimals
76
- /// /////////////////////////////
77
54
#[view]
78
- fn get_decimals () -> u8 {
79
- decimals :: read ()
55
+ fn decimals () -> u8 {
56
+ _decimals :: read ()
80
57
}
81
58
82
- /// /////////////////////////////
83
- // get_total_supply function returns token total total_supply
84
- /// /////////////////////////////
85
59
#[view]
86
- fn get_total_supply () -> u256 {
87
- total_supply :: read ()
60
+ fn total_supply () -> u256 {
61
+ _total_supply :: read ()
88
62
}
89
63
90
- /// /////////////////////////////
91
- // balance_of function returns balance of an account
92
- /// /////////////////////////////
93
64
#[view]
94
- fn balance_of (account : ContractAddress ) -> u256 {
95
- balances :: read (account )
65
+ fn balanceOf (account : ContractAddress ) -> u256 {
66
+ _balances :: read (account )
96
67
}
97
68
98
- /// /////////////////////////////
99
- // allowance function returns total allowamnce given to an account
100
- /// /////////////////////////////
101
69
#[view]
102
70
fn allowance (owner : ContractAddress , spender : ContractAddress ) -> u256 {
103
- allowances :: read ((owner , spender ))
71
+ _allowances :: read ((owner , spender ))
104
72
}
105
73
106
- /// /////////////////////////////
107
- // transfer function for transferring tokens from one account to another
108
- /// /////////////////////////////
109
74
#[external]
110
- fn transfer (recipient : ContractAddress , amount : u256 ) {
111
- let sender = get_caller_address ();
112
- transfer_helper (sender , recipient , amount );
75
+ fn approve (spender : ContractAddress , amount : u256 ) -> bool {
76
+ let owner = get_caller_address ();
77
+
78
+ _allowances :: write ((owner , spender ), amount );
79
+
80
+ Approval (owner , spender , amount );
81
+
82
+ true
113
83
}
114
84
115
- /// /////////////////////////////
116
- // transfer_from function for transferring tokens on behalf of another user
117
- /// /////////////////////////////
118
85
#[external]
119
- fn transfer_from (sender : ContractAddress , recipient : ContractAddress , amount : u256 ) {
120
- let caller = get_caller_address ();
121
- spend_allowance (sender , caller , amount );
122
- transfer_helper (sender , recipient , amount );
86
+ fn mint (amount : u256 ) {
87
+ let sender = get_caller_address ();
88
+
89
+ _total_supply :: write (_total_supply :: read () + amount );
90
+ _balances :: write (sender , _balances :: read (sender ) + amount );
123
91
}
124
92
125
- /// /////////////////////////////
126
- // approve function for approving another user to spend from an account balance
127
- /// /////////////////////////////
128
93
#[external]
129
- fn approve (spender : ContractAddress , amount : u256 ) {
130
- let caller = get_caller_address ();
131
- approve_helper (caller , spender , amount );
132
- }
94
+ fn transfer (to : ContractAddress , amount : u256 ) -> bool {
95
+ let from = get_caller_address ();
96
+
97
+ _balances :: write (from , _balances :: read (from ) - amount );
98
+ _balances :: write (to , _balances :: read (to ) + amount );
99
+
100
+ Transfer (from , to , amount );
133
101
134
- /// /////////////////////////////
135
- // internal function that contains the tranfer logic
136
- /// /////////////////////////////
137
- fn transfer_helper (sender : ContractAddress , recipient : ContractAddress , amount : u256 ) {
138
- assert (! sender . is_zero (), ' ERC20: transfer from 0' );
139
- assert (! recipient . is_zero (), ' ERC20: transfer to 0' );
140
- balances :: write (sender , balances :: read (sender ) - amount );
141
- balances :: write (recipient , balances :: read (recipient ) + amount );
142
- Transfer (sender , recipient , amount );
102
+ true
143
103
}
144
104
145
- /// /////////////////////////////
146
- // internal function implementing checks against unlimited allowance
147
- /// /////////////////////////////
148
- fn spend_allowance ( owner : ContractAddress , spender : ContractAddress , amount : u256 ) {
149
- let current_allowance = allowances :: read (( owner , spender ));
105
+ #[external]
106
+ fn transferFrom ( from : ContractAddress , to : ContractAddress , amount : u256 ) -> bool {
107
+ let caller = get_caller_address ();
108
+ let allowed : u256 = _allowances :: read (( from , caller ));
109
+
150
110
let ONES_MASK = 0xffffffffffffffffffffffffffffffff_u128 ;
151
- let is_unlimited_allowance =
152
- current_allowance . low == ONES_MASK & current_allowance . high == ONES_MASK ;
153
- if ! is_unlimited_allowance {
154
- approve_helper (owner , spender , current_allowance - amount );
111
+
112
+ let is_max = (allowed . low == ONES_MASK ) & (allowed . high == ONES_MASK );
113
+
114
+ if ! is_max {
115
+ _allowances :: write ((from , caller ), allowed - amount );
116
+ Approval (from , caller , allowed - amount );
155
117
}
156
- }
157
118
158
- /// /////////////////////////////
159
- // internal function containing the approval logic
160
- /// /////////////////////////////
161
- fn approve_helper (owner : ContractAddress , spender : ContractAddress , amount : u256 ) {
162
- assert (! spender . is_zero (), ' ERC20: approve from 0' );
163
- allowances :: write ((owner , spender ), amount );
164
- Approval (owner , spender , amount );
119
+ _balances :: write (from , _balances :: read (from ) - amount );
120
+ _balances :: write (to , _balances :: read (to ) + amount );
121
+
122
+ Transfer (from , to , amount );
123
+
124
+ true
165
125
}
166
126
}
0 commit comments