目录

  • 基本介绍
  • 代币标准的目的
  • ERC20代币标准
    • 最小单元
    • 可选单元
  • solidity 0.6.0版本以后的不同点
  • 实战代码展示(发币)

基本介绍

ERC 旨在建立使应用程序和合约更容易相互交互的约定

与 ETH(以太坊的原生加密货币)不同,ERC-20 代币不由账户持有代币只存在于合约中,就像一个自包含的数据库。它指定代币的规则(即名称、符号、可分割性)并保存一个将用户余额映射到他们的以太坊地址的列表。要移动代币,用户必须向合约发送交易,要求其将部分余额分配到其他地方。

当用户A调用转账函数,转给B部分金额时,这个调用会包含在一个看似常规的以太坊交易中,该交易向代币合约支付 0 ETH(交易的value为0)。该调用包含在交易的一个附加字段中,该字段指定 A想要做什么——在我们的例子中是将代币转移给 B,字段为Tokens Transferred。

注意:不要理解成当A调用转账函数,转的是A自身的以太币!只是代币!!
后续或许可以用代币来换取以太币

代币标准的目的

代币是以太坊这类通用编程区块链之上最显著和有用的应用形态。

  • 代币标准(ERC20、ERC721)是实现的最小单元
  • 使用代币标准,可完成合约之间的互操作性(多个合约去实现ERC20)
  • 安全

ERC20代币标准

最小单元

6个函数、2个事件

// 获取系统金额发行量function totalSupply() virtual public view returns (uint totalSupply);// 获取_owner余额function balanceOf(address _owner) virtual public view returns (uint balance);// 调用者(msg.sender)向 _t0 转账 _valuefunction transfer(address _to, uint256 _value) virtual public returns (bool success);// 下面两个函数通常一起使用// 2、授权后,被授权的人调用此函数,相当于手动取钱! 与transfer的区别在于 一个是甲方直接给你钱,一个是甲方授权,乙方自己取钱。function transferFrom(address _from, address _to, uint256 _value) virtual public returns (bool success);// 1、用于授权,msg.sender 授权给 _spender 可以动用 _valuefunction approve(address _spender, uint256 _value) virtual public returns (bool success);// 查看_owner 授权给 _spender 的余额数量function allowance(address _owner, address _spender) virtual public view returns (uint remaining);// 转账事件,每次发生转账交易后触发事件让别人知道event Transfer(address indexed _from, address indexed _to, uint256 _value);// 授权事件,每次发生一个地址给另一个地址授权后触发事件让别人知道event Approval(address indexed _owner, address indexed _spender, uint256 _value);

可选单元

代币的名称

function name() virtual public view returns (string calldata);

代币的代号、标识,通常为字母缩写

function symbol() virtual public view returns (string calldata);

返回令牌使用的小数位数 – 例如”8″,意味着将令牌量除以”100000000″以获取其用户的表示形式。

function decimals() virtual public view returns (uint8);

solidity 0.6.0版本以后的不同点

1、合约contract 关键字之前需要加上abstract修饰

2、在抽象的函数内,添加virtual关键字

3、在继承函数时,需要对继承的函数名中加上override修饰符


实战代码展示(发币)

ERC20.sol合约:

pragma solidity ^0.6.0;abstract contract ERC20 {    // function name() public view returns (string)    // function symbol() public view returns (string)    // function decimals() public view returns (uint8)    function totalSupply() virtual public view returns (uint totalSupply);    function balanceOf(address _owner) virtual public view returns (uint balance);    function transfer(address _to, uint256 _value) virtual public returns (bool success);    function transferFrom(address _from, address _to, uint256 _value) virtual public returns (bool success);    function approve(address _spender, uint256 _value) virtual public returns (bool success);    function allowance(address _owner, address _spender) virtual public view returns (uint remaining);    event Transfer(address indexed _from, address indexed _to, uint256 _value);    event Approval(address indexed _owner, address indexed _spender, uint256 _value);}

pcCoin.sol合约 继承自 ERC20

pragma solidity ^0.6.0;import "./ERC20.sol";contract pcCoin is ERC20{    uint256 _totalSupply; // 总供应量    address public  _owner; // 部署合约的人    uint8 public decimals = 18;  // 18 是建议的默认值    mapping(address=>uint256) _balances; // address的余额    mapping(address=>mapping(address=>uint256)) _approves; // a授权给b多少余额    // 转账事件,转过之后让人能看到    event Transfer(address indexed _from, address indexed _to, uint256 _value);    // 授权事件,授权之后让人能看到    event Approval(address indexed _owner, address indexed _spender, uint256 _value);    constructor(uint256 totalSupply) public {        _owner = msg.sender; // _owner初始化为部署合约的人        _totalSupply = totalSupply * 10 ** uint256(decimals);        _balances[msg.sender] = _totalSupply;    }    // 设置权限    modifier onlyOwner(){        require(msg.sender == _owner);        _;    }    //给指定账户投钱,只有部署合约的人有这个权限    function airDrop(address _to, uint256 _value) onlyOwner public {        require(_to != address(0) && _value > 0);        _balances[_to] = _value;        _totalSupply += _value; // 投过钱后,总供应量增加    }    // 返回总供应量    function totalSupply() override public view returns(uint totalSupply){        totalSupply = _totalSupply;        return totalSupply;    }    function balanceOf(address _owner) override public view returns(uint balance){        require(_owner != address(0), "owner should not be empty! ");        return _balances[_owner];    }    function transfer(address _to, uint256 _value) override public returns (bool success){        require(_to != address(0), "_to should not be empty !");        require(_balances[msg.sender] >= _value && _value>0, "value should be valid !!");        _balances[msg.sender] -= _value;        _balances[_to] += _value;        success = true;        emit Transfer(msg.sender, _to, _value);        return success;    }    // 被授权者来调用此函数,可理解为自己取钱,_from是授权的人    function transferFrom(address _from, address _to, uint256 _value) override public returns (bool success){        require(_from != address(0) && _to != address(0));        require(_approves[_from][msg.sender] >= _value); // _from 授权给 msg.sender 的钱必须大于 _value        _approves[_from][msg.sender] -= _value; // 取了钱后,_from 授权给 msg.sender 的钱就要减少        _balances[_to] += _value;        success = true;        emit Transfer(_from, _to, _value);        return success;    }    // 调用此函数,意为调用者(msg.sender)授权给_spender多少可动的钱    function approve(address _spender, uint256 _value) override public returns (bool success){        require(_spender != address(0));        require(_balances[msg.sender] >= _value && _value > 0);        _approves[msg.sender][_spender] += _value; // 授权        _balances[msg.sender] -= _value;         success = true;        emit Approval(msg.sender, _spender, _value);        return success;    }    function allowance(address _owner, address _spender) override public view returns (uint remaining){        return _approves[_owner][_spender];    }}

部署到区块链网络(我部署的是ropsten测试网络)

下面可以调函数

过一会,支付一些燃油费之后,就部署到ropsten测试网络了。此时


添加后自己的代币计算发布成功了!可以给别的地址转币