🎈亲爱的读者朋友们:
如果你觉得这篇文章对你有所帮助,恳请你为我点个赞👍。你的每一个赞都是对我辛勤创作的认可,是我继续前行的动力源泉。
同时,也欢迎你关注我的 CSDN 博客。在这里,我会持续分享更多实用的技术干货、独特的编程见解和宝贵的学习经验。
期待你的点赞与关注,让我们携手共进,共创更精彩的技术世界!
1.ERC20
什么叫做代币?
代币可以在以太坊中表示任何东西:
- 在线平台中的信誉积分
- 游戏中一个角色的技能
- 彩票卷
- 金融资产类似于公司股份的资产
- 像美元一样的法定货币
- 一盎司黄金
- 及更多...
以太坊的这种强大特点必须以强有力的标准来处理,对吗? 这正是 ERC-20 发挥其作用的地方! 此标准允许开发者构建可与其他产品和服务互相操作的代币应用程序。
什么是 ERC-20?
ERC-20 提出了一个同质化代币的标准,换句话说,它们具有一种属性,使得每个代币都与另一个代币(在类型和价值上)完全相同。 例如,一个 ERC-20 代币就像以太币一样,意味着一个代币会并永远会与其他代币一样。
ERC-20(以太坊意见征求 20)由 Fabian Vogelsteller 提出于 2015 年 11 月。这是一个能实现智能合约中代币的应用程序接口标准。
ERC-20 的功能示例包括:
- 将代币从一个帐户转到另一个帐户
- 获取帐户的当前代币余额
- 获取网络上可用代币的总供应量
- 批准一个帐户中一定的代币金额由第三方帐户使用
如果智能合约实施了下列方法和事件,它可以被称为 ERC-20 代币合约,一旦部署,将负责跟踪以太坊上创建的代币。
上面是官方的说法, 代币嘛,比如游戏:我们用金钱充值,经过一定换算,人民币对应的换算游戏的货币。这些游戏货币就是代币。
当然,只是打个比方,代币更多还是区块链所属的概念。
当然简单的来讲:
ERC20是以太坊定义的一个合约接口规范,符合该规范的合约被称为以太坊代币。
1.这是以太坊官方给的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);
我们就围绕ERC20自己写个代币合约。
顺便在代码注释出讲解相应功能。
2.自己写一个ERC20合约实现
1.ERC20
pragma solidity ^0.4.25;
interface ERC20 {
// 返回代币名称
function name()public view returns (string memory);
// 返回代币符号
function symbol()public view returns (string memory);
// 返回代币小数点后位数
function decimals()public view returns (uint8);
// 总代币数量
function totalSupply()public view returns (uint256);
// 返回 _owner 地址拥有的代币数量。
function balanceOf(address _owner)public view returns (uint256 balance);
// 将 value 数量的代币发送给 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
function transfer(address _to, uint256 _value)public returns (bool success);
// 将 value 数量的代币从 from 地址发送到 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
function transferFrom(address _from, address _to, uint256 _value)public returns (bool success);
// 授权 spender 可以花费 value 数量的代币,返回布尔值告知是否执行成功。触发 Approval 事件。
function approve(address _spender, uint256 _value)public returns (bool success);
// 返回授权花费者 spender 通过 transferFrom 代表所有者花费的剩余代币数量。
// 默认情况下为零。当 approve 和 transferFrom 被调用时,值将改变。
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);
}
2. Jzm20
contract Jzm20 is ERC20 {
///
Filed
///
uint256 private _totalSupply;
string private _symbol;
// 地址余额
mapping(address => uint256) private _balances;
// 授权地址余额
mapping(address => mapping(address => uint256)) private _allowances;
///
Function
///
constructor (string symbol_) public {
_symbol = symbol_;
}
function name() public view returns (string memory) {
return "Jzm20";
}
function symbol() public view returns (string memory){
return _symbol;
}
function decimals() public view returns (uint8){
return 18;
}
function totalSupply() public view returns (uint256){
return _totalSupply;
}
function balanceOf(address _owner) public view returns (uint256 balance){
balance = _balances[_owner];
}
// 给指定owner地址创建value数量代币
function mint(address _owner,uint256 _value) public {
require(_owner != address(0),"Jzm20: owner address is not empty");
_balances[_owner] = _value;
_totalSupply = _sum(_totalSupply,_value);
emit Transfer(address(0),_owner,_value);
}
function transfer(address _to, uint256 _value) public returns (bool success){
address owner = msg.sender;
_transfer(owner,_to,_value);
success = true;
}
function transferTo(address _from, address _to, uint256 _value) public returns(bool success) {
_transfer(_from,_to,_value);
success = true;
}
// 这个是给spender权限者使用的
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success){
address spender = msg.sender;
uint256 approveBalance = allowance(_from,spender);
_allowances[_from][spender] = _sub( _allowances[_from][spender],_value); // 相应地授权金额回增加
require(approveBalance >= _value,"Jzm20:approve balance is Insufficient balance transfer");
_transfer(_from,_to,_value);
success = true;
}
function approve(address _spender, uint256 _value) public returns (bool success){
address owner = msg.sender;
require(_balances[owner] >= _value,"Jzm20:owner balance is not enough to value memory!");
_allowances[msg.sender][_spender] = _sum( _allowances[msg.sender][_spender],_value);
emit Approval(owner,_spender,_value);
success = true;
}
function allowance(address _owner, address _spender) public view returns (uint256 remaining){
remaining = _allowances[_owner][_spender];
}
function _sum(uint256 a,uint256 b) private pure returns(uint256) {
uint256 c = a + b;
require(c >= a && c >= b,"Jm20:An arithmetic overflow has occurred");
return c;
}
function _sub(uint256 a,uint256 b) private pure returns(uint256) {
uint256 c = a - b;
require(c <= a,"Jm20:An arithmetic overflow Under has occurred");
return c;
}
function _transfer( address _from, address _to, uint256 _value) private {
require(_balances[_from] >= _value,"Jm20:owner balance is Insufficient balance transfer");
require(_to != address(0),"Jm20:to can not be empty address!");
_balances[_to] = _sum(_balances[_to],_value);
_balances[_from] = _sub(_balances[_from],_value);
emit Transfer(_from,_to,_value);
}
}