erc20需要实现以下方法
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
以及两个事件
event Transfer(address indexed _from, address indexed _to, uint256 _value)
event Approval(address indexed _owner, address indexed _spender, uint256 _value)
一.name()
虚拟货币的名称,我们可以创建一个String变量,可见性设为public,由于public会自动创建一个getter方法,所以不需要再创建额外的name()方法
string public name = "NilahToken";
二.symbol()
名称缩写,原理如上,继续创建String变量
string public symbol = "NLT";
三.decimals()
虚拟货币小数点后的位数,一般都是18位
uint256 public decimals = 18;
四.totalSupply()
货币数量,但在此处是创建的一个getter方法,用于返回创建的货币的数量
uint256 public totalSupply;
五.balanceof()
用于返回一个账户所拥有的此货币的数量,我们可以用mapping映射,address映射uint256,继续public,自动创建getter方法
mapping (address => uint256) public balanceOf;
六.transfer()
转账方法,简单点来说就是加减,这里麻烦了一点,是调用了另一个函数
function transfer(address _to, uint256 _value) public returns (bool success){
require(_to != address(0));
_transfer(msg.sender, _to, _value); //调用_transfer函数
return true;
}
七._transfer()
这是上面所调用的方法,这个方法有三个参数,_from从哪里转,_to转到哪里,_value转出数量
function _transfer(address _from, address _to, uint256 _value) internal{ //私有函数 用于调用
require(balanceOf[_from] >= _value);
balanceOf[_from] = balanceOf[_from].sub(_value);
balanceOf[_to] = balanceOf[_to].add(_value);
emit Transfer(_from,_to,_value);
}
require(balanceOf[_from] >= _value);
我们刚刚创建的映射balanceof,这里需要比较,balanceof[_from]为转出去的地址的余额,我要给_to转_value,那我的余额肯定得比_value多或者等于_value
balanceOf[_from] = balanceOf[_from].sub(_value);
balanceOf[_to] = balanceOf[_to].add(_value);
在转账成功过后,_from的账户肯定得减少_value,而收账的账户也得增加_value,这里的add与sub是调用了库里的方法,当然也可以不调用,简单粗暴的进行加减
emit Transfer(_from,_to,_value);
触发事件
七.transferFrom()
第三方转账,可以理解为平台交易,例如我给这个平台授权了多少代币,那么这个平台才可以使用多少代币
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
//msg.sender提供授权的账户
//_from交易所账户
//_value金额
require(balanceOf[_from] >= _value);
require(allowance[_from][msg.sender] >= _value); //授权金额大于转账金额
allowance[_from][msg.sender] = allowance[_from][msg.sender].sub(_value); //授权金额减去转账金额
_transfer(_from, _to, _value); //调用方法进行转账
return true;
}
这里面的allowance等会儿会提到
八.approve()
刚刚提到了第三方转账,转账的前提是需要授权,那么这个就是授权方法,添加一个映射用于存储账户所授权的值,在上一个方法中转账成功后,那么这值就会减少
mapping (address => mapping (address => uint256)) public allowance;
function approve(address _spender, uint256 _value) public returns (bool success){ //授权给交易所金额
//msg.sender当前账户
//_spender交易所地址
//_value金额
require(_spender != address(0));
allowance[msg.sender][_spender] = _value; //msg.sender授权给_spender交易所_value金额
emit Approval(msg.sender, _spender, _value);
return true;
}
由于刚刚的交易触发了两个事件,所以不要忘了把事件加上
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
以下为完整代码
pragma solidity >=0.4.16 <0.9.0;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
contract NilahToken{
using SafeMath for uint256;
string public name = "NilahToken";
string public symbol = "NLT";
uint256 public decimals = 18;
uint256 public totalSupply;
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);
constructor() {
totalSupply = 1000000 * (10 ** decimals);
balanceOf[msg.sender] = totalSupply;
}
function transfer(address _to, uint256 _value) public returns (bool success){
require(_to != address(0));
_transfer(msg.sender, _to, _value); //调用_transfer函数
return true;
}
function _transfer(address _from, address _to, uint256 _value) internal{ //私有函数 用于调用
require(balanceOf[_from] >= _value);
balanceOf[_from] = balanceOf[_from].sub(_value);
balanceOf[_to] = balanceOf[_to].add(_value);
emit Transfer(_from,_to,_value);
}
function approve(address _spender, uint256 _value) public returns (bool success){ //授权给交易所金额
//msg.sender当前账户
//_spender交易所地址
//_value金额
require(_spender != address(0));
allowance[msg.sender][_spender] = _value; //msg.sender授权给_spender交易所_value金额
emit Approval(msg.sender, _spender, _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
//msg.sender提供授权的账户
//_from交易所账户
//_value金额
require(balanceOf[_from] >= _value);
require(allowance[_from][msg.sender] >= _value); //授权金额大于转账金额
allowance[_from][msg.sender] = allowance[_from][msg.sender].sub(_value); //授权金额减去转账金额
_transfer(_from, _to, _value); //调用方法进行转账
return true;
}
}
1.规定版本
2.导入SafeMath库,方便后续使用sub、add方法
3.代码块里有注解
4.此代码复制粘贴即可使用,但是需要自行下载SafeMath库
5.代码名称以及代号在变量name和symbol处更改
6.Token位数可以在decimals处更改
7.存量是1000000,也可以在构造函数的totalSupply处更改