目录
- 基本介绍
- 代币标准的目的
- 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测试网络了。此时
添加后自己的代币计算发布成功了!可以给别的地址转币