-
Notifications
You must be signed in to change notification settings - Fork 6
/
ERC20.sol
138 lines (105 loc) · 4.13 KB
/
ERC20.sol
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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
import "../utils/FilAddress.sol";
/**
* @author fevmate (https://github.com/wadealexc/fevmate)
* @notice ERC20 mixin for the FEVM. This contract implements the ERC20
* standard, with additional safety features for the FEVM.
*
* All methods attempt to normalize address input. This means that if
* they are provided ID addresses as input, they will attempt to convert
* these addresses to standard Eth addresses.
*
* This is an important consideration when developing on the FEVM, and
* you can read about it more in the README.
*/
abstract contract ERC20 {
using FilAddress for *;
/*//////////////////////////////////////
TOKEN INFO
//////////////////////////////////////*/
string public name;
string public symbol;
uint8 public decimals;
/*//////////////////////////////////////
ERC-20 STORAGE
//////////////////////////////////////*/
uint public totalSupply;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowances;
/*//////////////////////////////////////
EVENTS
//////////////////////////////////////*/
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
/*//////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////*/
constructor (
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
}
/*//////////////////////////////////////
ERC-20 METHODS
//////////////////////////////////////*/
function transfer(address _to, uint _amount) public virtual returns (bool) {
// Attempt to convert destination to Eth address
_to = _to.normalize();
balances[msg.sender] -= _amount;
balances[_to] += _amount;
emit Transfer(msg.sender, _to, _amount);
return true;
}
function transferFrom(address _owner, address _to, uint _amount) public virtual returns (bool) {
// Attempt to convert owner and destination to Eth addresses
_owner = _owner.normalize();
_to = _to.normalize();
// Reduce allowance for spender. If allowance is set to the
// max value, we leave it alone.
uint allowed = allowances[_owner][msg.sender];
if (allowed != type(uint).max)
allowances[_owner][msg.sender] = allowed - _amount;
balances[_owner] -= _amount;
balances[_to] += _amount;
emit Transfer(_owner, _to, _amount);
return true;
}
function approve(address _spender, uint _amount) public virtual returns (bool) {
// Attempt to convert spender to Eth address
_spender = _spender.normalize();
allowances[msg.sender][_spender] = _amount;
emit Approval(msg.sender, _spender, _amount);
return true;
}
/*//////////////////////////////////////
ERC-20 GETTERS
//////////////////////////////////////*/
function balanceOf(address _a) public virtual view returns (uint) {
return balances[_a.normalize()];
}
function allowance(address _owner, address _spender) public virtual view returns (uint) {
return allowances[_owner.normalize()][_spender.normalize()];
}
/*//////////////////////////////////////
MINT/BURN INTERNAL METHODS
//////////////////////////////////////*/
function _mint(address _to, uint _amount) internal virtual {
// Attempt to convert to Eth address
_to = _to.normalize();
totalSupply += _amount;
balances[_to] += _amount;
emit Transfer(address(0), _to, _amount);
}
function _burn(address _from, uint _amount) internal virtual {
// Attempt to convert to Eth address
_from = _from.normalize();
balances[_from] -= _amount;
totalSupply -= _amount;
emit Transfer(_from, address(0), _amount);
}
}