-
Notifications
You must be signed in to change notification settings - Fork 29
/
TokenERC20.sol
138 lines (123 loc) · 5.24 KB
/
TokenERC20.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
pragma solidity >=0.4.22 <0.7.0;
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes calldata _extraData) external; }
contract TokenERC20 {
string public name;
string public symbol;
uint8 public decimals = 18; // decimals 可以有的小数点个数,最小的代币单位。18 是建议的默认值
uint256 public totalSupply;
// 用mapping保存每个地址对应的余额
mapping (address => uint256) public balanceOf;
// 存储对账号的控制
mapping (address => mapping (address => uint256)) public allowance;
// 事件,用来通知客户端交易发生
event Transfer(address indexed from, address indexed to, uint256 value);
// 事件,用来通知客户端代币被消费
event Burn(address indexed from, uint256 value);
/**
* 初始化构造
*/
constructor(uint256 initialSupply, string memory tokenName, string memory tokenSymbol) public {
totalSupply = initialSupply * 10 ** uint256(decimals); // 供应的份额,份额跟最小的代币单位有关,份额 = 币数 * 10 ** decimals。
balanceOf[msg.sender] = totalSupply; // 创建者拥有所有的代币
name = tokenName; // 代币名称
symbol = tokenSymbol; // 代币符号
}
/**
* 代币交易转移的内部实现
*/
function _transfer(address _from, address _to, uint _value) internal {
// 确保目标地址不为0x0,因为0x0地址代表销毁
require(_to != address(0x0));
// 检查发送者余额
require(balanceOf[_from] >= _value);
// 确保转移为正数个
require(balanceOf[_to] + _value > balanceOf[_to]);
// 以下用来检查交易,
uint previousBalances = balanceOf[_from] + balanceOf[_to];
// Subtract from the sender
balanceOf[_from] -= _value;
// Add the same to the recipient
balanceOf[_to] += _value;
emit Transfer(_from, _to, _value);
// 用assert来检查代码逻辑。
assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
}
/**
* 代币交易转移
* 从创建交易者账号发送`_value`个代币到 `_to`账号
*
* @param _to 接收者地址
* @param _value 转移数额
*/
function transfer(address _to, uint256 _value) public {
_transfer(msg.sender, _to, _value);
}
/**
* 账号之间代币交易转移
* @param _from 发送者地址
* @param _to 接收者地址
* @param _value 转移数额
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= allowance[_from][msg.sender]); // Check allowance
allowance[_from][msg.sender] -= _value;
_transfer(_from, _to, _value);
return true;
}
/**
* 设置某个地址(合约)可以交易者名义花费的代币数。
*
* 允许发送者`_spender` 花费不多于 `_value` 个代币
*
* @param _spender The address authorized to spend
* @param _value the max amount they can spend
*/
function approve(address _spender, uint256 _value) public
returns (bool success) {
allowance[msg.sender][_spender] = _value;
return true;
}
/**
* 设置允许一个地址(合约)以交易者名义可最多花费的代币数。
*
* @param _spender 被授权的地址(合约)
* @param _value 最大可花费代币数
* @param _extraData 发送给合约的附加数据
*/
function approveAndCall(address _spender, uint256 _value, bytes memory _extraData)
public
returns (bool success) {
tokenRecipient spender = tokenRecipient(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, address(this), _extraData);
return true;
}
}
/**
* 销毁创建者账户中指定个代币
*/
function burn(uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value); // Check if the sender has enough
balanceOf[msg.sender] -= _value; // Subtract from the sender
totalSupply -= _value; // Updates totalSupply
emit Burn(msg.sender, _value);
return true;
}
/**
* 销毁用户账户中指定个代币
*
* Remove `_value` tokens from the system irreversibly on behalf of `_from`.
*
* @param _from the address of the sender
* @param _value the amount of money to burn
*/
function burnFrom(address _from, uint256 _value) public returns (bool success) {
require(balanceOf[_from] >= _value); // Check if the targeted balance is enough
require(_value <= allowance[_from][msg.sender]); // Check allowance
balanceOf[_from] -= _value; // Subtract from the targeted balance
allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance
totalSupply -= _value; // Update totalSupply
emit Burn(_from, _value);
return true;
}
}