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
| pragma solidity ^0.4.16;
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }
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);
/** * 初始化构造 */ function TokenERC20(uint256 initialSupply, string tokenName, string 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 != 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; Transfer(_from, _to, _value);
// 用assert来检查代码逻辑。 assert(balanceOf[_from] + balanceOf[_to] == previousBalances); }
/** * 代币交易转移 * 从自己(创建交易者)账号发送`_value`个代币到 `_to`账号 * * @param _to 接收者地址 * @param _value 转移数额 */ function transfer(address _to, uint256 _value) public returns (bool) { _transfer(msg.sender, _to, _value); return true; }
/** * 账号之间代币交易转移 * @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 _extraData) public returns (bool success) { tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { // 通知合约 spender.receiveApproval(msg.sender, _value, 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 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 Burn(_from, _value); return true; } }
|