ERC20代币学习与合约编写
Posted bfengj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ERC20代币学习与合约编写相关的知识,希望对你有一定的参考价值。
前言
今天刷Ethernaut遇到了一道ERC20的题目,考虑到自己还没有实际用过ERC20,以及它的编写,就花了一个晚上写了点代码,可以发现自己的币。
简介
也许你经常看到ERC20和代币一同出现, ERC20是以太坊定义的一个代币标准。
要求我们在实现代币的时候必须要遵守的协议,如指定代币名称、总量、实现代币交易函数等,只有支持了协议才能被以太坊钱包支持。
登链社区关于ERC20的API规范:
代币标准
还有github的英文版标准:
代币标准
编写代码
规范中也推荐了几个比较好的实现实例:
实例,我就是学习了这些实例,然后自己编写了一遍。
ERC20Interface.sol
:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
interface ERC20Interface
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8 );
function totalSupply() external view returns (uint256 );
function balanceOf(address _owner) external view returns (uint256 balance);
function transfer(address _to, uint256 _value) external returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);
function approve(address _spender, uint256 _value) external returns (bool success);
function allowance(address _owner, address _spender) external view returns (uint256 remaining);
接口函数,这些函数的原型也都是上面的代币标准中摘录下来的。对于每个函数的用途也都做了解释。
然后就是继承接口并编写ERC20.sol
:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "./ERC20Interface.sol";
contract ERC20 is ERC20Interface
string public _name = "Feng";
string public _symbol = "FENG";
uint8 public _decimals = 18; // 18 是建议的默认值
uint256 public _totalSupply;
mapping (address => uint256) public _balanceOf;
mapping (address => mapping (address => uint256)) _allowance;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
function name() public view virtual override returns (string memory)
return _name;
function symbol() public view virtual override returns (string memory)
return _symbol;
function decimals() public view virtual override returns (uint8 )
return _decimals;
function totalSupply() public view virtual override returns (uint256 )
return _totalSupply;
function balanceOf(address _owner) public view virtual override returns (uint256 balance)
balance = _balanceOf[_owner];
function _transfer(address _from, address _to, uint256 _value) internal virtual
require(_from != address(0));
require(_to != address(0));
require(_balanceOf[_from] >= _value);
_balanceOf[msg.sender]-=_value;
_balanceOf[_to]+=_value;
emit Transfer(_from, _to, _value);
function _approve(address _owner, address _spender, uint256 _value) internal virtual
require(_owner != address(0));
require(_spender != address(0));
_allowance[_owner][_spender] = _value;
emit Approval(_owner, _spender, _value);
function transfer(address _to, uint256 _value) public virtual override returns (bool success)
_transfer(msg.sender, _to, _value);
success = true;
function transferFrom(address _from, address _to, uint256 _value) public virtual override returns (bool success)
_transfer(_from, _to, _value);
uint256 allowanceNum = _allowance[_from][_to];
require(allowanceNum >= _value);
_approve(_from, _to, allowanceNum - _value);
success = true;
function approve(address _spender, uint256 _value) public virtual override returns (bool success)
_approve(msg.sender, _spender, _value);
success = true;
function allowance(address _owner, address _spender) public view virtual override returns (uint256 remaining)
return _allowance[_owner][_spender];
function _mint(address _account, uint256 _value) internal virtual
require(_account != address(0));
_totalSupply += _value;
_balanceOf[_account] += _value;
emit Transfer(address(0), _account, _value);
其中也会多出来一些函数是接口中没有的,例如_mint
,是铸币函数。
再自己写一个Fun.sol
来用一下自己写的代币玩玩:
//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import "./ERC20.sol";
contract Fun is ERC20
address public owner;
constructor() payable
owner = msg.sender;
modifier onlyOwner()
require(msg.sender == owner);
_;
function mint(address _account, uint _value) public onlyOwner
_mint(_account, _value);
function getMoney() public
uint value = uint(keccak256(abi.encodePacked(block.timestamp))) % 10;
_mint(msg.sender, value);
即可使用了。需要注意那个_decimals = 18
,即有18位小数,因此一般的transfer这样的,如果value传1,其实是0.000000000000000001 FENG
,因此如果是1 FENG的话,value得是1000000000000000000
。
总结
学习了一下ERC20,同时写了一些代码,对于代币以及合约的继承的理解更深了。
开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系以上是关于ERC20代币学习与合约编写的主要内容,如果未能解决你的问题,请参考以下文章