ERC-20 提出了一个同质化代币的标准,换句话说,它们具有一种属性,使得每个代币都与另一个代币(在类型和价值上)完全相同。 例如,一个 ERC-20 代币就像以太币一样,意味着一个代币会并永远会与其他代币一样。(From: 《ERC-20 代币标准》)
function name() public view returns (string)
// 返回令牌的名称 - 例如 "MyToken"
// 可选 - 此方法可用于提高可用性,但接口和其他协定不得期望存在这些值。
function symbol() public view returns (string)
// 返回令牌的 symbol。例如“HIX”。
// 可选 - 此方法可用于提高可用性,但接口和其他协定不得期望存在这些值。
function decimals() public view returns (uint8)
// 返回代币使用的小数位数 - 例如 8,表示将代币数量除以 100000000 以获得其用户表示。
// 可选 - 此方法可用于提高可用性,但接口和其他协定不得期望存在这些值。
function totalSupply() public view returns (uint256)
// 返回总代币供应量。
function balanceOf(address _owner) public view returns (uint256 balance)
// 返回地址为 _owner 的另一个账户的账户余额。
function transfer(address _to, uint256 _value) public returns (bool success)
// 将 _value 数量的代币转移到 _to,并且必须触发 Transfer 事件。如果消息调用者的账户余额没有足够的代币可供花费,则函数应该throw。
// 注意值为 0 的传输必须被视为正常传输,并触发 Transfer 事件。
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
// 将 _value数量的代币从地址 _from 转移到地址 _to,并且必须触发 Transfer 事件。
// transferFrom 方法用于提现工作流程,允许合约代表您转移代币。例如,这可用于允许合约代表您转移代币和/或以子货币收取费用。除非 _from 账户通过某种机制故意授权了消息的发送者,否则该函数应该throw。
function approve(address _spender, uint256 _value) public returns (bool success)
// 允许_spender多次从您的账户提款,最高可达_value金额。如果再次调用此函数,它将用 _value 覆盖当前限额。
// 注意:客户端应该确保在创建用户界面时,先将限额设置为 0,然后再为同一花费者将其设置为另一个值。尽管 Contract 本身不应该强制执行它,以允许向后兼容之前部署的 Contract
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
// 返回 _spender 仍允许从 _owner 中提取的金额。
event Transfer(address indexed _from, address indexed _to, uint256 _value)
// 必须在代币转移时触发,包括零价值转移。
// 创建新代币的代币合约应该在创建代币时触发 Transfer 事件,并将 _from 地址设置为 0x0。
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
// 必须在成功调用 approve(address _spender, uint256 _value) 时触发。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract MyToken {
string public constant name = "Bob's Token";
string public constant symbol = "BBK";
uint8 public constant decimals = 18;
uint16 private constant increase = 1000;
uint256 public constant totalLimit = 27000000 * (10 ** decimals);
uint256 public totalSupply = 0;
address private owner;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
modifier checkAddress(address _addr) {
require(address(_addr) != address(0), "Invalid address.");
_;
}
modifier checkBalanceOf(address _addr, uint256 _value) {
require(balanceOf[_addr] >= _value, "Insufficient balance");
_;
}
modifier checkOwner() {
require(msg.sender == owner, "Not owner.");
_;
}
constructor() {
owner = msg.sender;
}
function mint(address _to) public checkOwner returns (uint256) {
uint256 mintValue = increase * (10 ** decimals);
require(totalLimit < (totalSupply + mintValue), "Out of limit.");
totalSupply += mintValue;
balanceOf[_to] += mintValue;
return balanceOf[_to];
}
function transfer(address _to, uint256 _value) public checkAddress(_to) checkBalanceOf(msg.sender, _value) returns (bool success){
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public checkAddress(_to) checkBalanceOf(_from, _value) returns (bool success) {
require(allowance[_from][msg.sender] >= _value, "No enough approve value.");
allowance[_from][msg.sender] -= _value;
balanceOf[_from] -= _value;
balanceOf[_to] += _value;
emit Transfer(_from, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success){
allowance[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
}
注意事项
由于本合约的编译版本为0.8.0,此版本具备整数溢出检查,所以可以不使用safeMath。
使用Open zeppelin快速创建ERC-20合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}
我们的合约通常通过[继承](https://solidity.readthedocs.io/en/latest/contracts.html#inheritance)来使用,在这里我们将 `ERC20` 重新用于基本标准实现以及 `name`、`symbol` 和 `decimals` 可选扩展。此外,我们正在创建一个代币的 `initialSupply`,该代币将被分配给部署合约的地址。(From: 《[ERC-20]()》)
