tp钱包怎么下载|erc20
ERC-20 代币标准 | ethereum.org
20 代币标准 | ethereum.org跳转至主要内容学习用法构建参与研究搜索语言 ZH帮助更新此页面本页面有新版本,但现在只有英文版。请帮助我们翻译最新版本。翻译页面没有错误!此页面未翻译,因此特意以英文显示。不再显示Change page概述基础主题以太坊简介以太币简介去中心化应用程序简介Web2 与 Web3 的对比帐户交易区块以太坊虚拟机 (EVM)操作码Gas费用节点和客户端运行节点客户端多样性节点即服务节点架构轻客户端归档节点引导节点网络共识机制工作量证明矿工挖矿算法Dagger-HashimotoEthash权益证明Gasper弱主观性认证权益证明机制的奖励和惩罚权益证明攻击与防御密钥权益证明与工作量证明提出区块权益正明常见问题以太坊堆栈堆栈简介智能合约智能合约语言智能合约结构智能合约库测试用智能合约编译智能合约部署智能合约验证智能合约升级智能合约智能合约安全性智能合约形式化验证可组合性开发网络开发框架以太坊客户端APIJavaScript API后端APIJSON-RPC数据和分析区块浏览器存储集成开发环境 (IDE)编程语言DartDelphi.NETGolangJavaJavaScriptPythonRubyRust语言高级链桥标准令牌标准ERC-20:同质化代币ERC-721:非同质化代币 (NFT)ERC-777ERC-1155ERC-4626最大可提取价值 (MEV)预言机缩放乐观卷叠零知识卷叠状态通道侧链以太坊 Plasma 扩容解决方案Validium数据可用性网络层网络地址门户网络数据结构与编码默克尔前缀树递归长度前缀编码 (RLP)简单序列化 (SSZ)Web3 密钥存储定义设计基础设计和用户体验简介ERC-20 代币标准p上次修改时间: @penglaishan.cn(opens in a new tab), Invalid DateTime查看贡献者在本页面介绍前提条件正文方法事件示例延伸阅读介绍什么叫做代币?代币可以在以太坊中表示任何东西:在线平台中的信誉积分游戏中一个角色的技能彩票卷金融资产类似于公司股份的资产像美元一样的法定货币一盎司黄金及更多...以太坊的这种强大特点必须以强有力的标准来处理,对吗? 这正是 ERC-20 发挥其作用的地方! 此标准允许开发者构建可与其他产品和服务互相操作的代币应用程序。什么是 ERC-20?ERC-20 提出了一个同质化代币的标准,换句话说,它们具有一种属性,使得每个代币都与另一个代币(在类型和价值上)完全相同。 例如,一个 ERC-20 代币就像以太币一样,意味着一个代币会并永远会与其他代币一样。前提条件帐户智能合约代币标准正文ERC-20(以太坊意见征求 20)由 Fabian Vogelsteller 提出于 2015 年 11 月。这是一个能实现智能合约中代币的应用程序接口标准。ERC-20 的功能示例包括:将代币从一个帐户转到另一个帐户获取帐户的当前代币余额获取网络上可用代币的总供应量批准一个帐户中一定的代币金额由第三方帐户使用如果智能合约实施了下列方法和事件,它可以被称为 ERC-20 代币合约,一旦部署,将负责跟踪以太坊上创建的代币。来自 EIP-20(opens in a new tab):方法1function name() public view returns (string)2function symbol() public view returns (string)3function decimals() public view returns (uint8)4function totalSupply() public view returns (uint256)5function balanceOf(address _owner) public view returns (uint256 balance)6function transfer(address _to, uint256 _value) public returns (bool success)7function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)8function approve(address _spender, uint256 _value) public returns (bool success)9function allowance(address _owner, address _spender) public view returns (uint256 remaining)显示全部 复制事件1event Transfer(address indexed _from, address indexed _to, uint256 _value)2event Approval(address indexed _owner, address indexed _spender, uint256 _value) 复制示例让我们看看如此重要的一个标准是如何使我们能够简单地检查以太坊上的任何 ERC-20 代币合约。 我们只需要合约的应用程序二进制接口 (ABI) 来创造一个 ERC-20 代币界面。 下面我们将使用一个简化的应用程序二进制接口,让例子变得更为简单。Web3.py 示例首先,请确保您已安装 Web3.py(opens in a new tab) Python 库:1pip install web31from web3 import Web3234w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))56dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI7weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH)89acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 21011# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract.12# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply()13simplified_abi = [14 {15 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}],16 'name': 'balanceOf',17 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],18 'stateMutability': 'view', 'type': 'function', 'constant': True19 },20 {21 'inputs': [],22 'name': 'decimals',23 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}],24 'stateMutability': 'view', 'type': 'function', 'constant': True25 },26 {27 'inputs': [],28 'name': 'symbol',29 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],30 'stateMutability': 'view', 'type': 'function', 'constant': True31 },32 {33 'inputs': [],34 'name': 'totalSupply',35 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],36 'stateMutability': 'view', 'type': 'function', 'constant': True37 }38]3940dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi)41symbol = dai_contract.functions.symbol().call()42decimals = dai_contract.functions.decimals().call()43totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals44addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals4546# DAI47print("===== %s =====" % symbol)48print("Total Supply:", totalSupply)49print("Addr Balance:", addr_balance)5051weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi)52symbol = weth_contract.functions.symbol().call()53decimals = weth_contract.functions.decimals().call()54totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals55addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals5657# WETH58print("===== %s =====" % symbol)59print("Total Supply:", totalSupply)60print("Addr Balance:", addr_balance)显示全部 复制延伸阅读EIP-20:ERC-20 代币标准(opens in a new tab)OpenZeppelin - 代币(opens in a new tab)OpenZeppelin - ERC-20 实施(opens in a new tab)back-to-top ↑本文对你有帮助吗?是否前一页令牌标准下一页ERC-721:非同质化代币 (NFT)编辑页面(opens in a new tab)在本页面介绍前提条件正文方法事件示例延伸阅读网站最后更新: 2024年2月16日(opens in a new tab)(opens in a new tab)(opens in a new tab)使用以太坊查找钱包获取以太币Dapps - 去中心化应用二层网络运行节点稳定币质押ETH学习学习中心什么是以太坊?什么是以太币 (ETH)?以太坊钱包Gas fees以太坊安全和预防欺诈措施什么是 Web3?智能合约以太坊能源消耗以太坊路线图以太坊改进提案 (Eip)以太坊的历史以太坊白皮书以太坊词汇表以太坊治理区块链桥零知识证明测试中心开发者开始体验相关文档教程通过编码来学习设置本地环境生态系统社区中心以太坊基金会以太坊基金会的博客(opens in a new tab)生态系统支持方案(opens in a new tab)以太坊漏洞悬赏计划生态系统资助计划以太坊品牌资产Devcon(opens in a new tab)企业级应用主网以太坊私密以太坊企业级应用关于ethereum.org关于我们工作机会参与贡献语言支持隐私政策使用条款缓存政策联系我们(opens in a new tERC-20是什么? - 知乎
ERC-20是什么? - 知乎切换模式写文章登录/注册ERC-20是什么?爱丽森梦游市场MBA/ 金融管理/区块链/人工智能什么是Token(代币)?在Ethereum中,代币几乎可以代表任何东西,从在线平台的信誉点、游戏中角色的技能、彩票到金融资产债券,再到真正的商品,如公司的股份、货币、金盎司等!如此强大的功能,值得也必须处理好。如此强大的功能,理应也必须由一个强大的标准来处理,对吗?这正是ERC-20的作用所在,ERC-20就是针对这些发布的Token(代币)制定的一个固定的基础的标准原则。什么是ERC-20?ERC-20引入了可替代Token(代币)的标准,换句话说,它们具有使每个Token(代币)与另一个Token(代币)完全相同(在类型和价值上)的属性。例如,ERC-20,Token(代币)的行为与ETH相同,这意味着任意1个遵循ERC-20规则的Token(代币)与所有其他所有Token(代币)是平等和相同的。由Fabian Vogelsteller在2015年11月提出的ERC-20(以太坊请求注释20)是一种Token标准,在智能合约中实现了Token的API。(注:API(token)是一个通用术语。通常,API(token)是请求访问您的服务的应用程序的唯一标识符。您的服务将为应用程序生成API(token),以供您在请求服务时使用。然后,您可以将它们提供的令牌与您存储的令牌进行匹配,以进行身份 验证)它提供的功能类似于将Token(代币)从一个帐户转移到另一个帐户,以获取帐户的当前Token(代币)钱包内的余额以及网络上可用Token(代币)的总供应量。除了这些之外,它还具有其他一些功能,例如批准第三方帐户可以使用帐户中的Token(代币)数量。如果智能合约实施以下方法和事件,则可以称为ERC-20 ,Token(代币)合约,一旦部署,它将负责在以太坊上跟踪创建的Token(代币)(注:网上拥有这种标准的ERC-20代码,就是为了方便程序员编程时候可以直接应用,有兴趣的可以自己搜索看看)ERC-20 定义通用规则?截至2019年10月,以太坊的主网络上存在超过200,000个与ERC-20兼容的Token(代币)。ERC-20至关重要。它定义了所有以太坊Token(代币)必须遵守的通用规则列表。这些规则中,包括如何传输Token(代币),如何批准交易,用户如何访问有关Token(代币)的数据以及Token(代币)的总供应量。 因此,这个特殊的Token(代币)使所有类型的开发人员都能准确地预测新Token(代币)在更大的以太坊系统中将如何运行。这简化了为开发人员设定的任务;他们可以继续进行自己的工作,因为只要Token(代币)遵循规则,就不需要在每次发布新Token(代币)时都重做每个新项目。它确保以太坊发行的许多不同令牌之间的兼容性。许多著名的数字货币都使用ERC-20标准:包括Maker(MKR),Basic Attention Token(BAT),Augur(REP)和OmiseGO(OMG)等,以及今年火爆的Defi(去中心化金融概念),诞生了如AAVE、Compound等优质项目,用户拥有USDT便可参与这些项目。如果您打算购买任何以ERC-20,Token(代币)发行的数字货币,则必须拥有一个与这些Token(代币)兼容的钱包。幸运的是,由于ERC-20,Token(代币)非常流行,因此钱包有很多不同的选择。如何确定某个代币是否为ERC20,Token(代币)呢?通过etherscan或者其他区块链平台查询:ERC-20代币有什么用?ERC20代币的出现,大幅降低了代币发行门槛。只要复制网上的标准代码,一个不懂编程的人也能在几分钟内,发行出一种新的Token(代币)。这一便利,也催生了2017年的「1CO」热潮,从而进一步推动了比特币牛市。目前全球Token(代币)总数超过5000种,绝大部分是ERC20的代币,据估计,至少占比超过95%,由此可见,ERC20是一种十分流行的代币格式。因为ERC20的标准token(代币)规则的便利性和统一性,前段时间的Defi热潮中ERC20,Token(代币)项目也表现得非常火爆:例如:LINK(预言机概念)取得了超过100倍的涨幅、UNI(去中心化交易所代币)创出了史上最强空投(人均1000美元)、UMA(衍生资产概念)获得了50倍的涨幅等等。发布于 2020-11-26 14:06token智能合约赞同 164 条评论分享喜欢收藏申请
智能合约ERC20代币详解 - 知乎
智能合约ERC20代币详解 - 知乎首发于区块链技术详解切换模式写文章登录/注册智能合约ERC20代币详解Zarten计算机技术与软件专业技术资格证持证人作者:Zarten知乎专栏:区块链技术详解知乎ID:Zarten简介: 互联网一线工作者,尊重原创并欢迎评论留言指出不足之处,也希望多些关注和点赞是给作者最好的鼓励 !概述ERC20并不是一项技术或者说一套程序,而是以太坊平台的数据通讯标准或者说规则 。ERC20简单理解成以太坊上的一个代币协议,所有基于以太坊开发的代币合约都遵守这个协议。遵守这些协议的代币我们可以认为是标准化的代币,而标准化带来的好处是兼容性好。这些标准化的代币可以被各种以太坊钱包支持,用于不同的平台和项目。ERC20标准官方介绍说明:https://theethereum.wiki/erc20_token_standard/标准规定,一共包括:6个函数,2个event,3个变量。 contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
string public constant name = "Zarten Token";
string public constant symbol = "ZAR";
uint8 public constant decimals = 18; // 18 is the most common number of decimal places
// 0.0000000000000000001 个代币
}
解释如下:totalSupply()代币发行总量。balanceOf(address tokenOwner)查询某个账户的代币余额。allowance(address tokenOwner, address spender)查询某个账户可转账金额。用于控制代币的交易。transfer(address to, uint tokens)从当前的自己账户,实现代币的交易。approve(address spender, uint tokens)设置允许某个账户spender从此地址可使用的代币数。transferFrom(address from, address to, uint tokens)实现用户之间的代币交易(非自己账户)。event Transfer(address indexed from, address indexed to, uint tokens)当代币交易时会触发此函数。event Approval(address indexed tokenOwner, address indexed spender, uint tokens)当成功调用approve函数后会触发此函数。name代币名称symbol 代币简称decimals 返回token使用的小数点后几位。比如如果设置为3,就是支持0.001表示。一般为18位。ERC20工作原理变量及函数实现定义变量一般会定义几个映射变量:mapping (address => uint256) public balances保存着每个地址对应的余额。mapping (address => mapping (address => uint256)) public allowed两层映射。保存着某个地址A允许另一个地址B可操作的金额。最外层映射为某个地址A,内层映射为另一个地址B,值为可操作(发起交易)金额总量。函数实现balanceOf()function balanceOf(address tokenOwner) public constant returns (uint balance) {
return balances[tokenOwner];
}
从映射变量balances中取出某个地址的余额。transfer()function transfer(address to, uint tokens) public returns (bool success) {
balances[msg.sender] = balances[msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
Transfer(msg.sender, to, tokens);
return true;
}
当前账户转账操作。msg.sender为保留字,指这个函数的地址。sub:减 add:加首先从当前账户减去相应金额。同时往对方账户加上对应金额。并调用Transfer函数做通知。transferFrom()function transferFrom(address from, address to, uint tokens) public returns (bool success){
balances[from] = balances[from].sub(tokens);
allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
balances[to] = balances[to].add(tokens);
Transfer(from, to, tokens);
return true;
}
用户之间账户转账操作。由from地址发起转账交易。from地址账户减去相应金额。from从msg.sender总共可操作金额减少相应金额。to地址账户增加相应金额。调用Transfer函数做通知。approve() function approve(address spender, uint tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
Approval(msg.sender, spender, tokens);
return true;
}
设置某账户spender可操控msg.sender的代币数。设置spender地址从msg.sender可使用的代币数。调用Approval函数做通知。举例说明假设2个钱包地址如下:balances[0x1111111111] = 100balances[0x2222222222] = 200 balanceOf()tokenContract.balanceOf(0x1111111111) will return 100tokenContract.balanceOf(0x2222222222) will return 200 transfer()若0x1111111111转账10个代币给0x2222222222,则0x1111111111将执行tokenContract.transfer(0x2222222222, 10)转账成功后得到如下结果:balances[0x1111111111] = 90balances[0x2222222222] = 210 approve()若0x1111111111允许0x2222222222拥有转账操作30个代币的权利,则0x1111111111将执行tokenContract.approve(0x2222222222, 30)设置成功后得到如下结果:tokenContract.allowed[0x1111111111][0x2222222222] = 30transferFrom()若0x2222222222转移0x1111111111的20个代币给自己,则0x2222222222将执行tokenContract.transferFrom(0x1111111111, 0x2222222222, 20)转账成功后得到如下结果:tokenContract.balances[0x1111111111] = 70tokenContract.balances[0x2222222222] = 230tokenContract.allowed[0x1111111111][0x2222222222] = 10 ERC20基本功能代码注:完整代币已上传至Github:GitHub - Zartenc/ZAR-ERC20: Zarten ERC20 Token is ZAR实现ERC标准接口,代码如下:pragma solidity ^0.4.0;
contract ERC20Interface {
function totalSupply() public view returns (uint);
function balanceOf(address tokenOwner) public view returns (uint balance);
function allowance(address tokenOwner, address spender) public view returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint tokens) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
contract ZartenToken is ERC20Interface{
string public name;
string public symbol;
uint8 public decimals;
uint256 public _totalSupply;
mapping (address => uint256) public balances;
mapping (address => mapping (address => uint256)) public allowed;
constructor() public {
symbol = "ZAR";
name = "Zarten Token";
decimals = 18;
_totalSupply = 100000000 * 10**uint256(decimals);
balances[msg.sender] = _totalSupply;
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address tokenOwner) public view returns (uint256 balance) {
return balances[tokenOwner];
}
function allowance(address tokenOwner, address spender) public view returns (uint remaining) {
return allowed[tokenOwner][spender];
}
function transfer(address to, uint256 tokens) public returns (bool success) {
// 检验接收者地址是否合法
require(to != address(0));
// 检验发送者账户余额是否足够
require(balances[msg.sender] >= tokens);
// 检验是否会发生溢出
require(balances[to] + tokens >= balances[to]);
// 扣除发送者账户余额
balances[msg.sender] -= tokens;
// 增加接收者账户余额
balances[to] += tokens;
// 触发相应的事件
emit Transfer(msg.sender, to, tokens);
return true;
}
function approve(address spender, uint256 tokens) public returns (bool success) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
function transferFrom(address from, address to, uint tokens) public returns (bool success) {
// 检验地址是否合法
require(to != address(0) && from != address(0));
// 检验发送者账户余额是否足够
require(balances[from] >= tokens);
// 检验操作的金额是否是被允许的
require(allowed[from][msg.sender] <= tokens);
// 检验是否会发生溢出
require(balances[to] + tokens >= balances[to]);
balances[from] -= tokens;
allowed[from][msg.sender] -= tokens;
balances[to] += tokens;
emit Transfer(from, to, tokens);
return true;
}
}
以上代码可直接部署并可调用。ERC20高级功能代码ERC20代币有时需要其他一些额外的高级功能,比如代币管理、代币增发、空投代币、代币冻结、销毁代币、代币兑换等。代币管理有时代币需要有一个管理者功能。添加一个owned合约,如下:contract Owned {
address public owner;
constructor() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address newOwner) onlyOwner public {
owner = newOwner;
}
}
上面modifier关键字为修饰器,修饰器所修饰的函数体会被插入到特殊符号 _; 的位置,如果是 owner 调用这个函数,则函数会被执行,否则会抛出异常。之后自己的合约继承ERC20Interface合约和owned合约,并msg.sender换为owner。contract ZartenToken is ERC20Interface, Owned{}代币增发代币增发可使代币总供应量增加,可以指定某个账户的代币增加,同时总供应量也随之增加。 //代币增发 function mintToken(address target, uint256 mintedAmount) onlyOwner public {
balances[target] += mintedAmount;
_totalSupply += mintedAmount;
emit Transfer(address(0), address(this), mintedAmount);
emit Transfer(address(this), target, mintedAmount);
}
使用onlyOwner修饰器,只能owner调用。this表示当前合约。代币销毁首先添加一个通知客户端代币消费的事件。event Burn(address indexed from, uint256 value);销毁代币非为销毁管理者代币和销毁用户代币。此时需要管理者去进行销毁。销毁管理者代币 //管理者代币销毁 function burn(uint256 _value) onlyOwner public returns (bool success) {
require(balances[owner] >= _value);
balances[owner] -= _value;
_totalSupply -= _value;
emit Burn(owner, _value);
return true;
}
销毁用户代币 //用户代币销毁 function burnFrom(address _from, uint256 _value) onlyOwner public returns (bool success) {
require(balances[_from] >= _value);
require(_value <= allowed[_from][owner]);
balances[_from] -= _value;
allowed[_from][owner] -= _value;
_totalSupply -= _value;
emit Burn(_from, _value);
return true;
}
代币冻结有时需要冻结账户代币,也就是此账户不能转账操作。1.首先添加一个账户冻结代币的映射mapping (address => bool) public frozenAccount;2.添加冻结的通知函数event FrozenFunds(address target, bool frozen);3..添加冻结的函数 //冻结账户代币 function freezeAccount(address target, bool freeze) onlyOwner public {
frozenAccount[target] = freeze;
emit FrozenFunds(target, freeze);
}
4.在转账函数中判断涉及账户是否为冻结账户,否则不允许转账操作 require(!frozenAccount[from]); require(!frozenAccount[to]);批量代币空投有时需要往很多地址空投一些代币,这样可以使用批量转账。假设从管理员账户空投。关键字memory为声明内存型的,存储的内容会在函数被调用(包括外部函数)时擦除,所以其使用开销相对较小。 //空投代币
function AirDrop(address[] memory _recipients, uint _values) onlyOwner public returns (bool) {
require(_recipients.length > 0);
for(uint j = 0; j < _recipients.length; j++){
transfer(_recipients[j], _values);
}
return true;
}
代币兑换有时代币需要与其他货币(Ether)进行兑换。msg.value表示随消息发送的wei的数量,payable修饰函数表示允许从调用中接收以太币。设置买卖价格的变量 uint256 public sellPrice; uint256 public buyPrice;设置价格函数 function setPrices(uint256 newSellPrice, uint256 newBuyPrice) onlyOwner public {
sellPrice = newSellPrice;
buyPrice = newBuyPrice;
}
接收以太币进行买操作 function buy() payable public {
uint amount = msg.value / buyPrice;
emit Transfer(address(this), owner, amount);
}
卖操作 function sell(uint256 amount) public {
require(address(this).balance >= amount * sellPrice);
emit Transfer(owner, address(this), amount);
owner.transfer(amount * sellPrice);
}
注:完整代币已上传至Github:GitHub - Zartenc/ZAR-ERC20: Zarten ERC20 Token is ZAR合约编译部署使用remix进行合约代码的编译与部署。官网:http://remix.ethereum.org/编译点击编译按钮;注意编译器版本与代码指定版本要对应。部署remix左侧的第三个按钮是发布按钮。点击发布按钮,会看到有ENVIRONMENT、ACCOUNT 、GAS LIMIT、CONTRACT等。其中,ENVIRONMENT有如下几个选项:1.JavaScript VM:这是Remix自己的内部沙箱。它不连接到MainNet,TestNet或任何专用网络。这是一个内存中的区块链,可用于简单测试和快速挖掘。2.Injected Web3:这是用于浏览器插件(MetaMask)的选项。在这里,Remix将对区块链集成的所有控制权交给MetaMask插件。此时,MetaMask控制要连接到的网络。3.Web3 Provider:这允许在Remix中输入URL以连接到区块链。此处最常见的设置是运行本地节点并通过其IP/端口连接到该节点此时选择 Injected Web3选项。点击Deploy部署后,小狐狸钱包会弹出确认框,此时需要注意选择的网络(主网或测试网等)。这里选择Goerli测试网络。部署成功后,可看到输出的日志和合约地址。此时部署已完成,也可在官方区块链浏览器中查看部署情况。钱包添加代币可把已经部署的代币添加到钱包方便查看,点击钱包添加代币,输入代币合约地址(上面箭头处)、代币符号、小数精度。输入信息如下:代币合约地址:0x9989a0ffB957D3eFf0262d43786df66176785F86代币符号:ZAR小数精度:18添加代币完成后如下所示:应用转账向另外一个地址转账1000个ZAR币,如下所示:转账成功后,另外一个账户收到1000个ZAR币。如下:代币信息总览可在浏览器中查看token详情,如下所示:查看ZAR币详情地址:https://goerli.etherscan.io/token/0x9989a0ffb957d3eff0262d43786df66176785f86#balances发布源代码若需要发布源代码可在浏览器中合约地址页面,Contract选项卡点击Verify and Publish ,接下来按提示步骤操作即可。发布于 2021-07-21 17:20token代币赞同 357 条评论分享喜欢收藏申请转载文章被以下专栏收录区块链技术详解区块链技术深
ERC-20 Token Standard | ethereum.org
20 Token Standard | ethereum.orgSkip to main contentLearnUseBuildParticipateResearchSearchLanguages ENHelp update this pageThere’s a new version of this page but it’s only in English right now. Help us translate the latest version.Translate pageNo bugs here!This page is not being translated. We've intentionally left this page in English for now.Don't show againChange pageOverviewFoundational topicsIntro to EthereumIntro to EtherIntro to dappsWeb2 vs Web3AccountsTransactionsBlocksEthereum virtual machine (EVM)OpcodesGasNodes and clientsRun a nodeClient diversityNodes as a serviceNode architectureLight clientsArchive nodesBootnodesNetworksConsensus mechanismsProof-of-workMiningMining algorithmsDagger-HashimotoEthashProof-of-stakeGasperWeak subjectivityAttestationsPoS rewards and penaltiesPoS attack and defenseKeysProof-of-stake versus proof-of-workBlock proposalProof-of-stake FAQsEthereum stackIntro to the stackSmart contractsSmart contract languagesSmart contract anatomySmart contracts librariesTesting smart contractsCompiling smart contractsDeploying smart contractsVerifying smart contractsUpgrading smart contractsSmart contract securitySmart contract formal verificationComposabilityDevelopment networksDevelopment frameworksEthereum client APIsJavaScript APIsBackend APIsJSON-RPCData and analyticsBlock explorersStorageIntegrated Development Environments (IDEs)Programming languagesDartDelphi.NETGolangJavaJavaScriptPythonRubyRustAdvancedBridgesStandardsToken standardsERC-20: Fungible TokensERC-721: NFTsERC-777ERC-1155ERC-4626Maximal extractable value (MEV)OraclesScalingOptimistic rollupsZero-knowledge rollupsState channelsSidechainsPlasmaValidiumData availabilityNetworking layerNetwork addressesPortal NetworkData structures and encodingPatricia Merkle TrieRecursive-length prefix (RLP)Simple serialize (SSZ)Web3 secret storage definitionDesign fundamentalsIntro to design and UXERC-20 Token StandardLast edit: , November 19, 2023See contributorsOn this pageIntroductionPrerequisitesBodyMethodsEventsExamplesFurther readingIntroductionWhat is a Token?Tokens can represent virtually anything in Ethereum:reputation points in an online platformskills of a character in a gamelottery ticketsfinancial assets like a share in a companya fiat currency like USDan ounce of goldand more...Such a powerful feature of Ethereum must be handled by a robust standard, right? That's exactlywhere the ERC-20 plays its role! This standard allows developers to build token applications that are interoperable with other products and services.What is ERC-20?The ERC-20 introduces a standard for Fungible Tokens, in other words, they have a property that makes each Token be exactly
the same (in type and value) as another Token. For example, an ERC-20 Token acts just like the ETH, meaning that 1 Token
is and will always be equal to all the other Tokens.PrerequisitesAccountsSmart ContractsToken standardsBodyThe ERC-20 (Ethereum Request for Comments 20), proposed by Fabian Vogelsteller in November 2015, is a Token Standard that
implements an API for tokens within Smart Contracts.Example functionalities ERC-20 provides:transfer tokens from one account to anotherget the current token balance of an accountget the total supply of the token available on the networkapprove whether an amount of token from an account can be spent by a third-party accountIf a Smart Contract implements the following methods and events it can be called an ERC-20 Token Contract and, once deployed, it
will be responsible to keep track of the created tokens on Ethereum.From EIP-20(opens in a new tab):Methods1function name() public view returns (string)2function symbol() public view returns (string)3function decimals() public view returns (uint8)4function totalSupply() public view returns (uint256)5function balanceOf(address _owner) public view returns (uint256 balance)6function transfer(address _to, uint256 _value) public returns (bool success)7function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)8function approve(address _spender, uint256 _value) public returns (bool success)9function allowance(address _owner, address _spender) public view returns (uint256 remaining)Show all CopyEvents1event Transfer(address indexed _from, address indexed _to, uint256 _value)2event Approval(address indexed _owner, address indexed _spender, uint256 _value) CopyExamplesLet's see how a Standard is so important to make things simple for us to inspect any ERC-20 Token Contract on Ethereum.
We just need the Contract Application Binary Interface (ABI) to create an interface to any ERC-20 Token. As you can
see below we will use a simplified ABI, to make it a low friction example.Web3.py ExampleFirst, make sure you have installed Web3.py(opens in a new tab) Python library:1pip install web31from web3 import Web3234w3 = Web3(Web3.HTTPProvider("https://cloudflare-eth.com"))56dai_token_addr = "0x6B175474E89094C44Da98b954EedeAC495271d0F" # DAI7weth_token_addr = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" # Wrapped ether (WETH)89acc_address = "0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11" # Uniswap V2: DAI 21011# This is a simplified Contract Application Binary Interface (ABI) of an ERC-20 Token Contract.12# It will expose only the methods: balanceOf(address), decimals(), symbol() and totalSupply()13simplified_abi = [14 {15 'inputs': [{'internalType': 'address', 'name': 'account', 'type': 'address'}],16 'name': 'balanceOf',17 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],18 'stateMutability': 'view', 'type': 'function', 'constant': True19 },20 {21 'inputs': [],22 'name': 'decimals',23 'outputs': [{'internalType': 'uint8', 'name': '', 'type': 'uint8'}],24 'stateMutability': 'view', 'type': 'function', 'constant': True25 },26 {27 'inputs': [],28 'name': 'symbol',29 'outputs': [{'internalType': 'string', 'name': '', 'type': 'string'}],30 'stateMutability': 'view', 'type': 'function', 'constant': True31 },32 {33 'inputs': [],34 'name': 'totalSupply',35 'outputs': [{'internalType': 'uint256', 'name': '', 'type': 'uint256'}],36 'stateMutability': 'view', 'type': 'function', 'constant': True37 }38]3940dai_contract = w3.eth.contract(address=w3.to_checksum_address(dai_token_addr), abi=simplified_abi)41symbol = dai_contract.functions.symbol().call()42decimals = dai_contract.functions.decimals().call()43totalSupply = dai_contract.functions.totalSupply().call() / 10**decimals44addr_balance = dai_contract.functions.balanceOf(acc_address).call() / 10**decimals4546# DAI47print("===== %s =====" % symbol)48print("Total Supply:", totalSupply)49print("Addr Balance:", addr_balance)5051weth_contract = w3.eth.contract(address=w3.to_checksum_address(weth_token_addr), abi=simplified_abi)52symbol = weth_contract.functions.symbol().call()53decimals = weth_contract.functions.decimals().call()54totalSupply = weth_contract.functions.totalSupply().call() / 10**decimals55addr_balance = weth_contract.functions.balanceOf(acc_address).call() / 10**decimals5657# WETH58print("===== %s =====" % symbol)59print("Total Supply:", totalSupply)60print("Addr Balance:", addr_balance)Show all CopyFurther readingEIP-20: ERC-20 Token Standard(opens in a new tab)OpenZeppelin - Tokens(opens in a new tab)OpenZeppelin - ERC-20 Implementation(opens in a new tab)Alchemy - Guide to Solidity ERC20 Tokens(opens in a new tab)back-to-top ↑Was this article helpful?YesNoPreviousToken standardsNextERC-721: NFTsEdit page(opens in a new tab)On this pageIntroductionPrerequisitesBodyMethodsEventsExamplesFurther readingWebsite last updated: February 16, 2024(opens in a new tab)(opens in a new tab)(opens in a new tab)Use EthereumFind walletGet ETHDapps - Decentralized applicationsLayer 2Run a nodeStablecoinsStake ETHLearnLearn HubWhat is Ethereum?What is ether (ETH)?Ethereum walletsGas feesEthereum security and scam preventionWhat is Web3?Smart contractsEthereum energy consumptionEthereum roadmapEthereum Improvement ProposalsHistory of EthereumEthereum WhitepaperEthereum glossaryEthereum governanceBlockchain bridgesZero-knowledge proofsQuiz HubDevelopersGet startedDocumentationTutorialsLearn by codingSet up local environmentEcosystemCommunity hubEthereum FoundationEthereum Foundation Blog(opens in a new tab)Ecosystem Support Program(opens in a new tab)Ethereum bug bounty programEcosystem Grant ProgramsEthereum brand assetsDevcon(opens in a new tab)EnterpriseMainnet EthereumPrivate EthereumEnterpriseAbout ethereum.orgAbout usJobsContributingLanguage supportPrivacy policyTerms of useCookie policyPress Contact(opens in a new t
ERC20解读 | 登链社区 | 区块链技术社区
ERC20解读 | 登链社区 | 区块链技术社区
文章
问答
讲堂
专栏
集市
更多
提问
发表文章
活动
文档
招聘
发现
Toggle navigation
首页 (current)
文章
问答
讲堂
专栏
活动
招聘
文档
集市
搜索
登录/注册
ERC20解读
Confucian
更新于 2022-04-04 19:54
阅读 6870
对ERC20代币标准的个人解读
# ERC20解读
**参考 **[**OpenZepplin文档**](https://docs.openzeppelin.com/contracts/4.x/erc20)** 和 **[**以太坊官方开发者文档**](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)**,结合自己的理解。**
博客的 Markdown 编辑器暂不支持 Solidity 语法高亮,为了更好阅读代码,可以去 [**我的GitHub仓库**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/tree/main/ERC20) 。
## **什么是ERC20**
**ERC20(Ethereum Request for Comments 20)一种代币标准。**[**EIP-20**](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md) 中提出。
**ERC20 代币合约跟踪同质化(可替代)代币:任何一个代币都完全等同于任何其他代币;没有任何代币具有与之相关的特殊权利或行为。这使得 ERC20 代币可用于交换货币、投票权、质押等媒介。**
## **为什么要遵守ERC20**
**EIP-20 中的动机:**
> **允许以太坊上的任何代币被其他应用程序(从钱包到去中心化交易所)重新使用的标准接口。**
**以太坊上的所有应用都默认支持 ERC20 ,如果你想自己发币,那么你的代码必须遵循 ERC20 标准,这样钱包(如MetaMask)等应用才能将你的币显示出来。**
## **代码实现**
**需要实现以下函数和事件:**
```
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)
```
**使用 OpenZeppllin 提供的库能够轻松快速地构建 ERC20 Token 。**
### **快速构建**
**这是一个 GLD token 。**
```
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}
```
**通常,我们定义代币的发行量和代币名称及符号。**
### **IERC20**
**先来看下 ERC20 的接口(IERC20),这方便我们在开发中直接定义 ERC20 代币。**
**同样地,OpenZepplin 为我们提供了相应的库,方便开发者导入即用。**
```
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
```
****EIP 中定义的 ERC20 标准接口:****
```
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
```
#### **逐一分析**
**函数:**
* `totalSupply()` :返回总共的代币数量。
* `balanceOf(address account)` :返回 `account` 地址拥有的代币数量。
* `transfer(address to, uint256 amount)` :将 **`amount`** 数量的代币发送给 **`to`** 地址,返回布尔值告知是否执行成功。触发 **`Transfer`** 事件。
* `allowance(address owner, address spender)` :返回授权花费者 **`spender`** 通过 **`transferFrom`** 代表所有者花费的剩余代币数量。默认情况下为零。当 **`approve`** 和 **`transferFrom`** 被调用时,值将改变。
* `approve(address spender, uint256 amount)` :授权 **`spender`** 可以花费 **`amount`** 数量的代币,返回布尔值告知是否执行成功。触发 **`Approval`** 事件。
* `transferFrom(address from, address to, uint256 amount)` :将 **`amount`** 数量的代币从 **`from`** 地址发送到 **`to`** 地址,返回布尔值告知是否执行成功。触发 **`Transfer`** 事件。
**事件(定义中的 **`indexed`** 便于查找过滤):**
* `Transfer(address from, address to, uint256 value)` :当代币被一个地址转移到另一个地址时触发。注意:转移的值可能是 0 。
* `Approval(address owner, address spender, uint256 value)` :当代币所有者授权别人使用代币时触发,即调用 **`approve`** 方法。
#### **元数据**
**一般除了上述必须实现的函数外,还有一些别的方法:**
* `name()` :返回代币名称
* `symbol()` :返回代币符号
* `decimals()` :返回代币小数点后位数
### **ERC20**
**来看下 ERC20 代币具体是怎么写的。**
**同样,OpenZepplin 提供了现成的合约代码:**
```
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
```
这里贴一个GitHub源码链接 [**OpenZepplin ERC20**](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
#### **函数概览**
```
constructor(name_, symbol_)
name()
symbol()
decimals()
totalSupply()
balanceOf(account)
transfer(to, amount)
allowance(owner, spender)
approve(spender, amount)
transferFrom(from, to, amount)
increaseAllowance(spender, addedValue)
decreaseAllowance(spender, subtractedValue)
_transfer(from, to, amount)
_mint(account, amount)
_burn(account, amount)
_approve(owner, spender, amount)
_spendAllowance(owner, spender, amount)
_beforeTokenTransfer(from, to, amount)
_afterTokenTransfer(from, to, amount)
```
****事件(同 IERC20)****
```
Transfer(from, to, value)
Approval(owner, spender, value)
```
#### **逐一分析**
* `constructor(string name, string symbol)` :设定代币的名称和符号。**`decimals`** 默认是 18 ,要修改成不同的值你应该重载它。这两个值是不变的,只在构造时赋值一次。
* `name()` :返回代币的名称。
* `symbol()` :返回代币的符号,通常是名称的缩写。
* `decimals()` :返回小数点后位数,通常是 18 ,模仿 Ether 和 wei 。要更改就重写它。
`totalSupply()、balanceOf(address account)、transfer(address to, uint256 amount)、 allowance(address owner, address spender)、approve(address spender, uint256 amount)、transferFrom(address from, address to, uint256 amount)` 都参考 IERC20 。
* `increaseAllowance(address spender, uint256 addedValue)` :以原子的方式增加 **`spender`** 额度。返回布尔值告知是否执行成功,触发 **`Approval`** 事件。
* `_transfer(address from, address to, uint256 amount)` :转账。这个内部函数相当于 **`transfer`** ,可以用于例如实施自动代币费用,削减机制等。触发 **`Transfer`** 事件。
* `_mint(address account, uint256 amount)` :铸造 **`amount`** 数量的代币给 **`account`** 地址,增加总发行量。触发 **`Transfer`** 事件,其中参数 **`from`** 是零地址。
* `_burn(address account, uint256 amount)` :从 **`account`** 地址中烧毁 **`amount`** 数量的代币,减少总发行量。触发 **`Transfer`** 事件,其中参数 **`to`** 是零地址。
* `_approve(address owner, uint256 spender, uint256 amount)` :设定允许 **`spender`** 花费 **`owner`** 的代币数量。这个内部函数相当于 **`approve`** ,可以用于例如为某些子系统设置自动限额等。
* `spendAllowance(address owner, address spender, uint256 amount)` :花费 **`amount`** 数量的 **`owner`** 授权 **`spender`** 的代币。在无限 allowance 的情况下不更新 allowance 金额。如果没有足够的余量,则恢复。可能触发 **`Approval`** 事件。
* `_beforeTokenTransfer(address from, address to, uint256 amount)` :在任何代币转账前的 Hook 。它包括铸币和烧毁。调用条件:
* **当 **`from`** 和 **`to`** 都不是零地址时,**`from` 手里 **`amount`** 数量的代币将发送给 **`to`** 。
* **当 **`from`** 是零地址时,将给 **`to`** 铸造 **`amount`** 数量的代币。**
* **当 **`to`** 是零地址时,**`from` 手里 **`amount`** 数量的代币将被烧毁。
* `from` 和 **`to`** 不能同时为零地址。
* `_afterTokenTransfer(address from, address to, uint256 amount)` :在任何代币转账后的 Hook 。它包括铸币和烧毁。调用条件:
* **当 **`from`** 和 **`to`** 都不是零地址时,**`from` 手里 **`amount`** 数量的代币将发送给 **`to`** 。
* **当 **`from`** 是零地址时,将给 **`to`** 铸造 **`amount`** 数量的代币。**
* **当 **`to`** 是零地址时,**`from` 手里 **`amount`** 数量的代币将被烧毁。
* `from` 和 **`to`** 不能同时为零地址。
#### **小结**
**ERC20 代码中的 **`_transfer`**、**`_mint`**、**`_burn`**、**`_approve`**、**`_spendAllowance`**、**`_beforeTokenTransfer`**、**`_afterTokenTransfer` 都是 **`internal`** 函数(其余为 **`public`** ),也就是说它们只能被派生合约调用。
## **从零开始,自己动手**
### **1.编写IERC20**
[**IERC20.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/IERC20.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
/// @dev 总发行量
function totoalSupply() external view returns (uint256);
/// @dev 查看地址余额
function balanceOf(address account) external view returns (uint256);
/// @dev 单地址转账
function transfer(address account, uint256 amount) external returns (bool);
/// @dev 查看被授权人代表所有者花费的代币余额
function allowance(address owner, address spender) external view returns (uint256);
/// @dev 授权别人花费你拥有的代币
function approve(address spender, uint256 amount) external returns (bool);
/// @dev 双地址转账
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/// @dev 发生代币转移时触发
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev 授权时触发
event Approval(address indexed owner, address indexed spender, uint256 value);
}
```
### **2.加上Metadata**
[**IERC20Metadata.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/IERC20Metadata.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "IERC20.sol";
interface IERC20Metadata is IERC20 {
/// @dev 代币名称
function name() external view returns (string memory);
/// @dev 代币符号
function symbol() external view returns (string memory);
/// @dev 小数点后位数
function decimals() external view returns (uint8);
}
```
### **3.编写ERC20**
[**ERC20.sol**](https://github.com/Blockchain-Engineer-Learning/Contract-Interpretation/blob/main/ERC20/contracts/ERC20.sol)
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC20Metadata.sol";
contract ERC20 is IERC20, IERC30Metadata {
// 地址余额
mapping(address => uint256) private _balances;
// 授权地址余额
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/// @dev 设定代币名称符号
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/// @dev 小数点位数一般为 18
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = msg.sender;
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = msg.sender;
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 substractedValue) public virtual returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= substractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approval(owner, spender, currentAllowance - substractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender];
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
```
## **总结**
**ERC20 其实就是一种最常见的代币标准,它明确了同质化代币的经典功能并规范了开发者编写 token 时的代码,从而方便各种应用适配。**
ERC20解读
参考 OpenZepplin文档 和 以太坊官方开发者文档,结合自己的理解。
博客的 Markdown 编辑器暂不支持 Solidity 语法高亮,为了更好阅读代码,可以去 我的GitHub仓库 。
什么是ERC20
ERC20(Ethereum Request for Comments 20)一种代币标准。EIP-20 中提出。
ERC20 代币合约跟踪同质化(可替代)代币:任何一个代币都完全等同于任何其他代币;没有任何代币具有与之相关的特殊权利或行为。这使得 ERC20 代币可用于交换货币、投票权、质押等媒介。
为什么要遵守ERC20
EIP-20 中的动机:
允许以太坊上的任何代币被其他应用程序(从钱包到去中心化交易所)重新使用的标准接口。
以太坊上的所有应用都默认支持 ERC20 ,如果你想自己发币,那么你的代码必须遵循 ERC20 标准,这样钱包(如MetaMask)等应用才能将你的币显示出来。
代码实现
需要实现以下函数和事件:
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)
使用 OpenZeppllin 提供的库能够轻松快速地构建 ERC20 Token 。
快速构建
这是一个 GLD token 。
// contracts/GLDToken.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract GLDToken is ERC20 {
constructor(uint256 initialSupply) ERC20("Gold", "GLD") {
_mint(msg.sender, initialSupply);
}
}
通常,我们定义代币的发行量和代币名称及符号。
IERC20
先来看下 ERC20 的接口(IERC20),这方便我们在开发中直接定义 ERC20 代币。
同样地,OpenZepplin 为我们提供了相应的库,方便开发者导入即用。
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
EIP 中定义的 ERC20 标准接口:
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
逐一分析
函数:
totalSupply() :返回总共的代币数量。
balanceOf(address account) :返回 account 地址拥有的代币数量。
transfer(address to, uint256 amount) :将 amount 数量的代币发送给 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
allowance(address owner, address spender) :返回授权花费者 spender 通过 transferFrom 代表所有者花费的剩余代币数量。默认情况下为零。当 approve 和 transferFrom 被调用时,值将改变。
approve(address spender, uint256 amount) :授权 spender 可以花费 amount 数量的代币,返回布尔值告知是否执行成功。触发 Approval 事件。
transferFrom(address from, address to, uint256 amount) :将 amount 数量的代币从 from 地址发送到 to 地址,返回布尔值告知是否执行成功。触发 Transfer 事件。
事件(定义中的 indexed 便于查找过滤):
Transfer(address from, address to, uint256 value) :当代币被一个地址转移到另一个地址时触发。注意:转移的值可能是 0 。
Approval(address owner, address spender, uint256 value) :当代币所有者授权别人使用代币时触发,即调用 approve 方法。
元数据
一般除了上述必须实现的函数外,还有一些别的方法:
name() :返回代币名称
symbol() :返回代币符号
decimals() :返回代币小数点后位数
ERC20
来看下 ERC20 代币具体是怎么写的。
同样,OpenZepplin 提供了现成的合约代码:
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
这里贴一个GitHub源码链接 OpenZepplin ERC20
函数概览
constructor(name_, symbol_)
name()
symbol()
decimals()
totalSupply()
balanceOf(account)
transfer(to, amount)
allowance(owner, spender)
approve(spender, amount)
transferFrom(from, to, amount)
increaseAllowance(spender, addedValue)
decreaseAllowance(spender, subtractedValue)
_transfer(from, to, amount)
_mint(account, amount)
_burn(account, amount)
_approve(owner, spender, amount)
_spendAllowance(owner, spender, amount)
_beforeTokenTransfer(from, to, amount)
_afterTokenTransfer(from, to, amount)
事件(同 IERC20)
Transfer(from, to, value)
Approval(owner, spender, value)
逐一分析
constructor(string name, string symbol) :设定代币的名称和符号。decimals 默认是 18 ,要修改成不同的值你应该重载它。这两个值是不变的,只在构造时赋值一次。
name() :返回代币的名称。
symbol() :返回代币的符号,通常是名称的缩写。
decimals() :返回小数点后位数,通常是 18 ,模仿 Ether 和 wei 。要更改就重写它。
totalSupply()、balanceOf(address account)、transfer(address to, uint256 amount)、 allowance(address owner, address spender)、approve(address spender, uint256 amount)、transferFrom(address from, address to, uint256 amount) 都参考 IERC20 。
increaseAllowance(address spender, uint256 addedValue) :以原子的方式增加 spender 额度。返回布尔值告知是否执行成功,触发 Approval 事件。
_transfer(address from, address to, uint256 amount) :转账。这个内部函数相当于 transfer ,可以用于例如实施自动代币费用,削减机制等。触发 Transfer 事件。
_mint(address account, uint256 amount) :铸造 amount 数量的代币给 account 地址,增加总发行量。触发 Transfer 事件,其中参数 from 是零地址。
_burn(address account, uint256 amount) :从 account 地址中烧毁 amount 数量的代币,减少总发行量。触发 Transfer 事件,其中参数 to 是零地址。
_approve(address owner, uint256 spender, uint256 amount) :设定允许 spender 花费 owner 的代币数量。这个内部函数相当于 approve ,可以用于例如为某些子系统设置自动限额等。
spendAllowance(address owner, address spender, uint256 amount) :花费 amount 数量的 owner 授权 spender 的代币。在无限 allowance 的情况下不更新 allowance 金额。如果没有足够的余量,则恢复。可能触发 Approval 事件。
_beforeTokenTransfer(address from, address to, uint256 amount) :在任何代币转账前的 Hook 。它包括铸币和烧毁。调用条件:
当 from 和 to 都不是零地址时,from 手里 amount 数量的代币将发送给 to 。
当 from 是零地址时,将给 to 铸造 amount 数量的代币。
当 to 是零地址时,from 手里 amount 数量的代币将被烧毁。
from 和 to 不能同时为零地址。
_afterTokenTransfer(address from, address to, uint256 amount) :在任何代币转账后的 Hook 。它包括铸币和烧毁。调用条件:
当 from 和 to 都不是零地址时,from 手里 amount 数量的代币将发送给 to 。
当 from 是零地址时,将给 to 铸造 amount 数量的代币。
当 to 是零地址时,from 手里 amount 数量的代币将被烧毁。
from 和 to 不能同时为零地址。
小结
ERC20 代码中的 _transfer、_mint、_burn、_approve、_spendAllowance、_beforeTokenTransfer、_afterTokenTransfer 都是 internal 函数(其余为 public ),也就是说它们只能被派生合约调用。
从零开始,自己动手
1.编写IERC20
IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC20 {
/// @dev 总发行量
function totoalSupply() external view returns (uint256);
/// @dev 查看地址余额
function balanceOf(address account) external view returns (uint256);
/// @dev 单地址转账
function transfer(address account, uint256 amount) external returns (bool);
/// @dev 查看被授权人代表所有者花费的代币余额
function allowance(address owner, address spender) external view returns (uint256);
/// @dev 授权别人花费你拥有的代币
function approve(address spender, uint256 amount) external returns (bool);
/// @dev 双地址转账
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/// @dev 发生代币转移时触发
event Transfer(address indexed from, address indexed to, uint256 value);
/// @dev 授权时触发
event Approval(address indexed owner, address indexed spender, uint256 value);
}
2.加上Metadata
IERC20Metadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "IERC20.sol";
interface IERC20Metadata is IERC20 {
/// @dev 代币名称
function name() external view returns (string memory);
/// @dev 代币符号
function symbol() external view returns (string memory);
/// @dev 小数点后位数
function decimals() external view returns (uint8);
}
3.编写ERC20
ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./IERC20Metadata.sol";
contract ERC20 is IERC20, IERC30Metadata {
// 地址余额
mapping(address => uint256) private _balances;
// 授权地址余额
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/// @dev 设定代币名称符号
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/// @dev 小数点位数一般为 18
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = msg.sender;
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = msg.sender;
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = msg.sender;
_approve(owner, spender, _allowances[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 substractedValue) public virtual returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = _allowances[owner][spender];
require(currentAllowance >= substractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approval(owner, spender, currentAllowance - substractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
}
_balances[to] += amount;
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender];
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
总结
ERC20 其实就是一种最常见的代币标准,它明确了同质化代币的经典功能并规范了开发者编写 token 时的代码,从而方便各种应用适配。
学分: 39
分类: 以太坊
标签:
ERC20
点赞 3
收藏 5
分享
Twitter分享
微信扫码分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
你可能感兴趣的文章
花式发币法之发行各类 ERC20 代币
3907 浏览
Michael.W基于Foundry精读Openzeppelin第39期——ERC20.sol
483 浏览
教程:如何在没有 Web 界面的情况下创建 ERC20桥
1561 浏览
一个简单的ERC20代币空投合约
2610 浏览
发布一款ERC20代币,并开发成Dapp
1517 浏览
Aptos合约开发之部署ERC20合约
3915 浏览
相关问题
如何从发起部署的地址中,转移一部分代币到已经部署的合约地址中,麻烦那位大佬看一下
5 回答
空投的默克尔树如何防止生日攻击?
2 回答
bsc链上的erc20合约,要求只有一点买卖的时候2%兑换成bnb发送到营销钱包,现在的问题是添加流动性会一直报错Fail with error 'TransferHelper::transferFrom: transferFrom failed'
2 回答
eth中如何判断合约是erc20合约
2 回答
寻找使用Vyper部署的带有交易税的ERC20代币模版
1 回答
如何实现同质化代币(ERC20标准)购买非同质化代币(ERC721)两份合约如何交互
3 回答
0 条评论
请先 登录 后评论
Confucian
关注
贡献值: 57
学分: 83
Keep Learning
文章目录
关于
关于我们
社区公约
学分规则
Github
伙伴们
ChainTool
为区块链开发者准备的开源工具箱
合作
广告投放
发布课程
联系我们
友情链接
关注社区
Discord
Youtube
B 站
公众号
关注不错过动态
微信群
加入技术圈子
©2024 登链社区 版权所有 |
Powered By Tipask3.5|
粤公网安备 44049102496617号
粤ICP备17140514号
粤B2-20230927
增值电信业务经营许可证
×
发送私信
请将文档链接发给晓娜,我们会尽快安排上架,感谢您的推荐!
发给:
内容:
取消
发送
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
取消
举报
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!
什么是ERC-20?关于ERC代币你应该了解的知识点 - 知乎
什么是ERC-20?关于ERC代币你应该了解的知识点 - 知乎首发于AAX学院切换模式写文章登录/注册什么是ERC-20?关于ERC代币你应该了解的知识点AAX学院高流动,低点差——尽在aax.com你应该听说过ERC-20代币,特别是如果你关注过2017年ICO热潮期间的加密领域。然而,除了ERC-20之外,还有许多其他的以太坊代币标准,比如ERC-721和ERC-223,它们给代币提供了更多的用例。在这篇文章中,作为以太坊区块链之旅的一部分,我们主要探索最重要的ERC代币标准。“ERC”是什么意思?ERC是Ethereum Request for Comment的缩写,用于对代币和以太坊生态系统提出改进建议。提交ERC后,以太坊社区将对其进行评估,并决定是否接受或拒绝该建议。获得绿灯后,ERC将被正式确定为以太坊改进建议(EIP)。虽然ERC大多是初始和非正式的建议,但EIP总是由以太坊核心开发者进行审核和评估。说到这里,”ERC “这个词在加密货币社区中广为人知,它是以太坊网络上代币的标准。简而言之,代币标准是用来定义数据和实现它的每个代币的功能。代币的标准化使得创作者更容易发行币,并将其与应用程序集成。ERC-20范例: Tether (USDT), Chainlink (LINK), AAX Token (AAB)ERC-20是以太坊生态系统中最流行的代币标准,也是整个加密货币行业中最流行的代币标准。ERC-20是由以太坊联合创始人Vitalik Buterin在2015年6月提出的,它是一个简单的接口,允许开发者在以太坊区块链之上创建他们的代币,并将其与第三方应用程序(如钱包和交易所)集成。除了允许创建者使用简单的功能,比如限制他们的币的总供应量,ERC-20代币、去中心化应用(DApps)和智能合约之间也有直接的互动。需要强调的是,ERC-20代币是可以互换的资产。就像百元大钞或标准金条一样,可互换代币是具有等值单位的相同资产。由于创建ERC-20代币很容易,大多数加密项目在2017年的ICO热潮中使用该标准来发行他们的原生币,并将其出售给出资者。因此,ERC-20是加密行业最广泛接受的代币标准,大多数数字资产钱包、交易所(包括AAX)和其他服务都支持该标准。ERC223范例:暂无ERC-223是以太坊生态系统中的一个可互换代币标准,其主要目标是解决ERC-20的一些问题。虽然ERC-20在加密项目和用户中非常受欢迎,但它允许人们将加密货币发送到智能合约而不是钱包。因此,一些用户由于合约失败或其他原因而失去了他们的资金。为了解决这个问题,ERC-223有一个功能,在用户不小心将代币发送到智能合约的情况下,会自动提醒用户。这样的交易会被自动取消,让用户收回资金(但还是要支付矿工费)。虽然它向下兼容ERC-20币,但ERC-223的特点是比之更低廉的矿工费。然而,尽管ERC-223具有优势,但它未能被以太坊社区采用,也尚未有加密项目使用该代币标准。ERC-721范例: CryptoKitties, Sorare与ERC-20和ERC-223相反,ERC-721是一个不可替代的代币(NFT)标准。这里的每个代币不是相同的硬币,而是独一无二的,具有自己的标识符,便于通过区块链进行验证。虽然可互换代币具有类似于标准金条或同值美元钞票的功能,但ERC-721币更像是艺术品或其他(复杂的)手工制作的物品,每件物品都是独一无二的,在某些方面与其他物品不同。虽然它们有多种应用,但NFT最受欢迎的用例是在区块链游戏解决方案中。通过非同质的代币,区块链游戏玩家可以收集、拥有和交易独特的游戏物品,如武器、角色、衣服、坐骑和车辆。此外,ERC-721代币标准允许创作者在多个区块链游戏和应用中集成NFT,让游戏玩家无论在哪里玩都能使用他们的数字收藏品。ERC-1155范例:EnjinERC-1155是一种混合代币标准,允许开发人员在一个智能合约下创建无限的可替代代币和不可替代代币。开发者在使用ERC-721时必须为每个NFT创建一个新的智能合约,而在使用ERC-1155时,他们只需要为非可替代代币和可互替代代币部署一个智能合约,从而缩短了开发时间,并最大限度地减少了创建者使用的资源。在区块链游戏中,这使得加密货币项目可以使用单一的智能合约来发行他们的游戏内货币作为可替代的代币,同时让用户在参与游戏的过程中收集NFT项目。关于AAX学院AAX是由LSEG Technology公司提供技术支持的数字资产交易所。AAX学院是AAX打造的一档用户教育频道,旨在帮助更多用户学习新手教程和了解到关于区块链的基础知识。 发布于 2020-09-22 08:38首次代币发行(ICO)数字化资产token赞同 51 条评论分享喜欢收藏申请转载文章被以下专栏收录AAX学院带来最前沿的区块链资讯知识,探究区块链背后
ERC-20 合约概览 | ethereum.org
20 合约概览 | ethereum.org跳转至主要内容学习用法构建参与研究搜索语言 ZH帮助更新此页面本页面有新版本,但现在只有英文版。请帮助我们翻译最新版本。翻译页面没有错误!此页面未翻译,因此特意以英文显示。不再显示ERC-20 合约概览solidityerc-20初学者Ori Pomerantz 2021年3月9日35 分钟阅读 minute read在本页面简介接口实际合约导入声明合约定义变量的定义构造函数用户接口函数读取代币信息代币转账许可额度函数修改代币信息的函数修改小数点设置变量钩子简介以太坊最常见的用途之一是由一个团队来打造一种可以交易的代币,在某种意义上是他们自己的货币。 这些代币通常遵循一个标准, ERC-20。 此标准使得人们能够以此来开发可以用于所有 ERC-20 代币的工具,如流动资金池和钱包。 在这篇文章中,我们将带领大家分析 OpenZeppelin Solidity ERC20 实现(opens in a new tab)以及 ERC20 接口定义(opens in a new tab)。这里使用的是附加说明的源代码。 如果想要实现 ERC-20, 请阅读此教程(opens in a new tab)。接口像 ERC-20 这样的标准,其目的是允许符合标准的多种代币,都可以在应用程序之间进行互操作,例如钱包和分布式交易所。 为实现这个目的,我们要创建一个 接口(opens in a new tab)。 任何需要使用代币合约的代码 可以在接口中使用相同的定义,并且与使用它的所有代币合约兼容。无论是像 MetaMask 这样的钱包、 诸如 etherscan.io 之类的去中心化应用程序,或一种不同的合约,例如流动资金池。如果您是一位经验丰富的程序员,您可能记得在 Java(opens in a new tab) 中,甚至在 C 头文件(opens in a new tab) 中看到过类似的构造。这是来自 OpenZeppelin 的 ERC-20 接口(opens in a new tab) 的定义。 这是将人类可读标准(opens in a new tab)转换为 Solidity 代码。 当然, 接口本身并不定义如何做事。 这一点在下文合约的源代码中作了解释。1// SPDX-License-Identifier: MIT 复制Solidity 文件中一般需要标识软件许可证。 您可以在这里看到许可证列表(opens in a new tab)。 如果需要不同的 许可证,只需在注释中加以说明。1pragma solidity >=0.6.0 <0.8.0; 复制Solidity 语言仍在迅速地发展,新版本可能不适配旧的代码 (请点击此处查看(opens in a new tab))。 因此,最好不仅指定一个最低的 语言版本,也指定一个最高的版本,即测试过代码的最新版本。1/**2 * @dev Interface of the ERC20 standard as defined in EIP.3 */ 复制注释中的 @dev 是 NatSpec 格式(opens in a new tab)的一部分,用于 从源代码生成文档。1interface IERC20 { 复制根据惯例,接口名称以 I 开头。1 /**2 * @dev Returns the amount of tokens in existence.3 */4 function totalSupply() external view returns (uint256); 复制此函数标记为 external,表示它只能从合约之外调用(opens in a new tab)。 它返回的是合约中代币的总供应量 这个值按以太坊中最常见的类型返回,即无符号的 256 位(256 位是 以太坊虚拟机的原生字长宽度)。 此函数也是视图 view 类型,这意味着它不会改变合约状态,这样它可以在单个节点上执行,而不需要在区块链的每个节点上执行。 这类函数不会生成交易,也不会消耗燃料。注意:理论上讲,合约创建者可能会通过返回比实际数量少的总供应量来做骗局,让每个代币 比实际看起来更有价值。 然而,这种担忧忽视了区块链的真正内涵。 所有在区块链上发生的事情都要通过每个节点 进行验证。 为了实现这一点,每个合约的机器语言代码和存储都可以在每个节点上找到。 虽然无需发布您的合约代码,但这样其它人都不会认真对待您,除非您发布源代码和用于编译的 Solidity 版本,这样人们可以用它来验证您提供的机器语言代码。 例如,请查看此合约(opens in a new tab)。1 /**2 * @dev Returns the amount of tokens owned by `account`.3 */4 function balanceOf(address account) external view returns (uint256); 复制顾名思义,balanceOf 返回一个账户的余额。 以太坊帐户在 Solidity 中通过 address 类型识别,该类型有 160 位。 它也是 external 和 view 类型。1 /**2 * @dev Moves `amount` tokens from the caller's account to `recipient`.3 *4 * Returns a boolean value indicating whether the operation succeeded.5 *6 * Emits a {Transfer} event.7 */8 function transfer(address recipient, uint256 amount) external returns (bool); 复制transfer 函数将代币从调用者地址转移到另一个地址。 这涉及到状态的更改,所以它不是 view 类型。 当用户调用此函数时,它会创建交易并消耗燃料。 还会触发一个 Transfer 事件,以通知区块链上的所有人。该函数有两种输出,对应两种不同的调用:直接从用户接口调用函数的用户。 此类用户通常会提交一个交易 并且不会等待响应,因为响应可能需要无限期的时间。 用户可以查看交易收据 (通常通过交易哈希值识别)或者查看 Transfer 事件,以确定发生了什么。将函数作为整个交易一部分调用的其他合约 这些合约可立即获得结果, 由于它们在相同的交易里运行,因此可以使用函数返回值。更改合约状态的其他函数创建的同类型输出。限额允许帐户使用属于另一位所有者的代币。 比如,当合约作为卖方时,这个函数就很实用。 合约无法 监听事件,如果买方要将代币直接转给卖方合约, 该合约无法知道已经获得付款。 因此,买方允许 卖方合约支付一定的额度,而让卖方转账相应金额。 这通过卖方合约调用的函数完成,这样卖方合约 可以知道是否成功。1 /**2 * @dev Returns the remaining number of tokens that `spender` will be3 * allowed to spend on behalf of `owner` through {transferFrom}. This is4 * zero by default.5 *6 * This value changes when {approve} or {transferFrom} are called.7 */8 function allowance(address owner, address spender) external view returns (uint256); 复制allowance 函数允许任何人查询一个 地址 (owner) 给另一个地址 (spender) 的许可额度。1 /**2 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.3 *4 * Returns a boolean value indicating whether the operation succeeded.5 *6 * IMPORTANT: Beware that changing an allowance with this method brings the risk7 * that someone may use both the old and the new allowance by unfortunate8 * transaction ordering. One possible solution to mitigate this race9 * condition is to first reduce the spender's allowance to 0 and set the10 * desired value afterwards:11 * https://github.com/ethereum/EIPs/issues/20#issuecomment-26352472912 *13 * Emits an {Approval} event.14 */15 function approve(address spender, uint256 amount) external returns (bool);显示全部 复制approve 函数创建了一个许可额度。 请务必阅读关于 如何避免函数被滥用的信息。 在以太坊中,您可以控制自己交易的顺序, 但无法控制其他方交易的执行顺序, 除非在看到其他方的交易发生之前 不提交您自己的交易。1 /**2 * @dev Moves `amount` tokens from `sender` to `recipient` using the3 * allowance mechanism. `amount` is then deducted from the caller's4 * allowance.5 *6 * Returns a boolean value indicating whether the operation succeeded.7 *8 * Emits a {Transfer} event.9 */10 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);显示全部 复制最后,消费者使用 transferFrom 函数用来使用许可额度。12 /**3 * @dev Emitted when `value` tokens are moved from one account (`from`) to4 * another (`to`).5 *6 * Note that `value` may be zero.7 */8 event Transfer(address indexed from, address indexed to, uint256 value);910 /**11 * @dev Emitted when the allowance of a `spender` for an `owner` is set by12 * a call to {approve}. `value` is the new allowance.13 */14 event Approval(address indexed owner, address indexed spender, uint256 value);15}显示全部 复制在 ERC-20 合约状态发生变化时就会激发这些事件。实际合约这是实现 ERC-20 标准的实际合约, 摘自此处(opens in a new tab)。 不能照原样使用,但可以 通过继承(opens in a new tab)将其扩展,使之可用。1// SPDX-License-Identifier: MIT2pragma solidity >=0.6.0 <0.8.0; 复制导入声明除了上述接口定义外,合约定义还要导入两个其他文件:12import "../../GSN/Context.sol";3import "./IERC20.sol";4import "../../math/SafeMath.sol"; 复制GSN/Context.sol 是使用 OpenGSN(opens in a new tab) 所需的文件,该系统允许用户在没有以太币的情况下 使用区块链。 请注意,这里的文件是旧版本,如果需要集成 OpenGSN, 请使用此教程(opens in a new tab)。SafeMath 库(opens in a new tab),用于 完成没有溢出问题的加法和减法。 这非常必要,否则会出现,用户仅有一个代币,花掉 两个代币后,反而有了 2^256-1 个代币。这里的注释说明了合约的目的。1/**2 * @dev Implementation of the {IERC20} interface.3 *4 * This implementation is agnostic to the way tokens are created. This means5 * that a supply mechanism has to be added in a derived contract using {_mint}.6 * For a generic mechanism see {ERC20PresetMinterPauser}.7 *8 * TIP: For a detailed writeup see our guide9 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How10 * to implement supply mechanisms].11 *12 * We have followed general OpenZeppelin guidelines: functions revert instead13 * of returning `false` on failure. This behavior is nonetheless conventional14 * and does not conflict with the expectations of ERC20 applications.15 *16 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.17 * This allows applications to reconstruct the allowance for all accounts just18 * by listening to said events. Other implementations of the EIP may not emit19 * these events, as it isn't required by the specification.20 *21 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}22 * functions have been added to mitigate the well-known issues around setting23 * allowances. See {IERC20-approve}.24 */25显示全部 复制合约定义1contract ERC20 is Context, IERC20 { 复制此行为 OpenGSN 指定继承,在本例中来自上面的 IERC20 和 Context。12 using SafeMath for uint256;3 复制此行将 SafeMath 库附加到 uint256 类型。 您可以在 此处(opens in a new tab)找到此程序库。变量的定义这些定义具体指定了合约的状态变量。 虽然声明这些变量为 private,但 这只意味着区块链上的其他合约无法读取它们。 区块链上 没有秘密,所有节点上的软件在每个区块上 都有每个合约的状态。 根据惯例,状态变量名称为 _ERC20 - 廖雪峰的官方网站
ERC20 - 廖雪峰的官方网站
Index
廖雪峰的官方网站
Blog
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
More
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
Java教程
手写Spring
手写Tomcat
Makefile教程
Python教程
JavaScript教程
区块链教程
SQL教程
Git教程
文章
问答
Profile
Passkey
Sign Out
Sign In
English
简体中文
Index
区块链教程
比特币
区块链原理
P2P交易原理
私钥
公钥和地址
签名
挖矿原理
可编程支付原理
多重签名
UTXO模型
Segwit地址
HD钱包
钱包层级
助记词
地址监控
以太坊
账户
区块结构
交易
智能合约
编写合约
部署合约
调用合约
编写Dapp
常用合约
ERC20
Wrapped Ether
关注公众号不定期领红包:
加入知识星球社群:
关注微博获取实时动态:
ERC20
Last updated: ...
/
Reads: 56789
Edit
ERC20是以太坊定义的一个合约接口规范,符合该规范的合约被称为以太坊代币。
一个ERC20合约通过mapping(address => uint256)存储一个地址对应的余额:
contract MyERC20 {
mapping(address => uint256) public balanceOf;
}
如果要在两个地址间转账,实际上就是对balanceOf这个mapping的对应的kv进行加减操作:
contract MyERC20 {
mapping(address => uint256) public balanceOf;
function transfer(address recipient, uint256 amount) public returns (bool) {
// 不允许转账给0地址:
require(recipient != address(0), "ERC20: transfer to the zero address");
// sender的余额必须大于或等于转账额度:
require(balanceOf[msg.sender] >= amount, "ERC20: transfer amount exceeds balance");
// 更新sender转账后的额度:
balanceOf[msg.sender] -= amount;
// 更新recipient转账后的额度:
balanceOf[recipient] += amount;
// 写入日志:
emit Transfer(sender, recipient, amount);
return true;
}
}
安全性
早期ERC20转账最容易出现的安全漏洞是加减导致的溢出,即两个超大数相加溢出,或者减法得到了负数导致结果错误。从Solidity 0.8版本开始,编译器默认就会检查运算溢出,因此,不要使用早期的Solidity编译即可避免溢出问题。
没有正确实现transfer()函数会导致交易成功,却没有任何转账发生,此时外部程序容易误认为已成功,导致假充值:
function transfer(address recipient, uint256 amount) public returns (bool) {
if (balanceOf[msg.sender] >= amount) {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
} else {
return false;
}
}
实际上transfer()函数返回bool毫无意义,因为条件不满足必须抛出异常回滚交易,这是ERC20接口定义冗余导致部分开发者未能遵守规范导致的。
ERC20另一个严重的安全性问题来源于重入攻击:
function transfer(address recipient, uint256 amount) public returns (bool) {
require(recipient != address(0), "ERC20: transfer to the zero address");
uint256 senderBalance = balanceOf[msg.sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
// 此处调用另一个回调:
callback(msg.sender);
// 更新转账后的额度:
balanceOf[msg.sender] = senderBalance - amount;
balanceOf[recipient] += amount;
emit Transfer(sender, recipient, amount);
return true;
}
先回调再更新的方式会导致重入攻击,即如果callback()调用了外部合约,外部合约回调transfer(),会导致重复转账。防止重入攻击的方法是一定要在校验通过后立刻更新数据,不要在校验-更新中插入任何可能执行外部代码的逻辑。
Comments
Make a comment
Sign in to
make a comment
Index
区块链教程
比特币
区块链原理
P2P交易原理
私钥
公钥和地址
签名
挖矿原理
可编程支付原理
多重签名
UTXO模型
Segwit地址
HD钱包
钱包层级
助记词
地址监控
以太坊
账户
区块结构
交易
智能合约
编写合约
部署合约
调用合约
编写Dapp
常用合约
ERC20
Wrapped Ether
廖雪峰的官方网站
©Copyright 2019-2021
Powered by iTranswarp
Feedback
License
EIP 20: ERC-20 代币标准(Token Standard) | 以太坊改进提案 EIPs
EIP 20: ERC-20 代币标准(Token Standard) | 以太坊改进提案 EIPs
以太坊改进提案 EIPs
首页
区块链文档中心
En
GitHub
首页
区块链文档中心
En
GitHub
EIPs 核心提案 接口提案 网络提案 应用标准提案(ERC) 所有标准提案(ERC)EIP 20: ERC-20 代币标准(Token Standard)简要说明摘要动机API 规范实现讨论历史版权EIP 55: 混合大小写校验和地址编码EIP 137 : 以太坊域名服务规范EIP 162: Initial ENS Hash RegistrarEIP 165: ERC-165 标准接口检测EIP 181: ENS 支持反向解析以太坊地址EIP 190: Ethereum Smart Contract Packaging StandardEIP 721: ERC-721 非同质化代币标准EIP 777: ERC777 代币标准EIP 1155: ERC-1155 多代币标准EIP 1167: 最小代理合约EIP 1820: 伪自省注册表合约EIP 875: 可批量即原子交换的简单非同质代币过程提案(Meta) 信息提案(Informational) # EIP 20: ERC-20 代币标准(Token Standard) 作者 状态 类型 分类 创建时间 Fabian Vogelsteller, Vitalik Buterin Final Standards Track ERC 2015-11-19 # 简要说明 代币(Token)的标准接口。 Token 亦有人翻译为通证,指在以太坊上通过智能合约发行的资产(或权益)。 # 摘要 本标准说明了在智能合约中实现代币的标准API。 该标准提供了代币的基本功能:如转移代币,授权代币给其他人(如链上第三方应用)使用。 # 动机 标准接口允许以太坊上的任何代币被其他应用程序重用,如钱包、去中心化交易所等。 # API 规范 # 函数 注意: API 规范使用 Solidity 0.4.17(或以上版本)的语法 调用者必须处理 returns (bool success) 返回false , 不能假定false不会返回。 # 可选函数: name 函数返回代币的名称 - 如 "MyToken" 或 "我的代币" 此函数是可选函数,但是这个函数可以提高代币可用性,不过调用者不能假定这个函数存在。 function name() public view returns (string)
1# 可选函数: symbol 函数返回代币的代号(通常为字母缩写),如 "HIX","UPT"。 此函数是可选函数,但是这个函数可以提高代币可用性,不过调用者不能假定这个函数存在。 function symbol() public view returns (string)
1# 可选函数: decimals 返回令牌使用的小数位数 - 例如"8",意味着将令牌量除以"100000000"以获取其用户表示形式。 此函数是可选函数,但是这个函数可以提高代币可用性,不过调用者不能假定这个函数存在。 function decimals() public view returns (uint8)
1# 函数: totalSupply 返回总令牌供应量。 function totalSupply() public view returns (uint256)
1# 函数: balanceOf 返回帐户(通过参数"_owner")的余额。 function balanceOf(address _owner) public view returns (uint256 balance)
1# 函数: transfer 向 _to 地址转移 _value 数量的代币,函数必须触发事件 Transfer 。 如果调用方的帐户余额没有足够的令牌,则该函数需要抛出异常。 注意 转移0个代币也是正常转移动作,同样需要触发 Transfer 事件。 function transfer(address _to, uint256 _value) public returns (bool success)
1# 函数: transferFrom 从 _from 向 _to 地址转移 _value 数量的代币,函数必须触发事件 Transfer 。 transferFrom 函数,可以允许第三方代表我们转移代币。 如果 _from 账号没有授权调用帐户转移代币,则该函数需要抛出异常。 注意 转移0个代币也是正常转移动作,同样需要触发 Transfer 事件。 function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
1# 函数: approve 授权 _spender 可以从我们账户最多转移代币的数量 _value,可以多次转移,总量不超过 _value 。 这个函数可以再次调用,以覆盖授权额度 _value 。 注意: 为了阻止向量攻击(这里有描述 和讨论 ),调用者可以在调整授权额度时,先设置为0,然后在设置为一个其他额度。 简单描述下:向量攻击, 假如 Alice 开始时给Bob授权了 N, 现在 Alice 想调整为 M ,于是发起了一笔调整授权的交易,这时Bob观察到了这笔交易, 迅速通过 transferFrom 交易(用更高的手续费,矿工优先打包)把 N 个币转移走,待 Alice 调整授权的交易打包后,Bob 又获得了 M 个授权。 这就相当于Bob 获得了 N + M个授权, 而不是 Alice 想要的 M个授权。 function approve(address _spender, uint256 _value) public returns (bool success)
1# 函数: allowance 查询 _owner 授权给 _spender 的额度。 function allowance(address _owner, address _spender) public view returns (uint256 remaining)
1# 事件Events # 事件:Transfer 当有代币转移时(包括转移0),必须触发 Transfer 事件。 如果是新产生代币,触发 Transfer 事件的 _from 应该设置为 0x0 。 event Transfer(address indexed _from, address indexed _to, uint256 _value)
1# 事件:Approval approve(address _spender, uint256 _value) 函数成功执行时,必须触发 Approval 事件。 event Approval(address indexed _owner, address indexed _spender, uint256 _value)
1# 实现 在以太坊网络上已经有大量符合 ERC20 的代币。
各个团队有不同的实现, 有些注重安全性,有些关注使用更少的gas。 # 实现示例 OpenZeppelin ConsenSys 实现 # 讨论历史 相关讨论的历史链接: Original proposal from Vitalik Buterin: https://github.com/ethereum/wiki/wiki/Standardized_Contract_APIs/499c882f3ec123537fc2fccd57eaa29e6032fe4a Reddit discussion: https://www.reddit.com/r/ethereum/comments/3n8fkn/lets_talk_about_the_coin_standard/ Original Issue #20: https://github.com/ethereum/EIPs/issues/20 # 版权 原文采用CC0 , 本翻译采用BY-NC-ND 许可协议,译者:深入浅出区块链 Tiny熊。 帮助完善文档 Last Updated: 9/4/2019, 11:28:22 PM
←
所有标准提案(ERC)
EIP 55: 混合大小写校验和地址编码
→
What Are ERC-20 Tokens on the Ethereum Network?
What Are ERC-20 Tokens on the Ethereum Network?
Investing
Stocks
Bonds
ETFs
Options and Derivatives
Commodities
Trading
FinTech and Automated Investing
Brokers
Fundamental Analysis
Technical Analysis
Markets
View All
Simulator
Login / Portfolio
Trade
Research
My Games
Leaderboard
Banking
Savings Accounts
Certificates of Deposit (CDs)
Money Market Accounts
Checking Accounts
View All
Personal Finance
Budgeting and Saving
Personal Loans
Insurance
Mortgages
Credit and Debt
Student Loans
Taxes
Credit Cards
Financial Literacy
Retirement
View All
News
Markets
Companies
Earnings
CD Rates
Mortgage Rates
Economy
Government
Crypto
ETFs
Personal Finance
View All
Reviews
Best Online Brokers
Best Savings Rates
Best CD Rates
Best Life Insurance
Best Personal Loans
Best Mortgage Rates
Best Money Market Accounts
Best Auto Loan Rates
Best Credit Repair Companies
Best Credit Cards
View All
Academy
Investing for Beginners
Trading for Beginners
Become a Day Trader
Technical Analysis
All Investing Courses
All Trading Courses
View All
Trade
Search
Search
Please fill out this field.
Search
Search
Please fill out this field.
Investing
Investing
Stocks
Bonds
ETFs
Options and Derivatives
Commodities
Trading
FinTech and Automated Investing
Brokers
Fundamental Analysis
Technical Analysis
Markets
View All
Simulator
Simulator
Login / Portfolio
Trade
Research
My Games
Leaderboard
Banking
Banking
Savings Accounts
Certificates of Deposit (CDs)
Money Market Accounts
Checking Accounts
View All
Personal Finance
Personal Finance
Budgeting and Saving
Personal Loans
Insurance
Mortgages
Credit and Debt
Student Loans
Taxes
Credit Cards
Financial Literacy
Retirement
View All
News
News
Markets
Companies
Earnings
CD Rates
Mortgage Rates
Economy
Government
Crypto
ETFs
Personal Finance
View All
Reviews
Reviews
Best Online Brokers
Best Savings Rates
Best CD Rates
Best Life Insurance
Best Personal Loans
Best Mortgage Rates
Best Money Market Accounts
Best Auto Loan Rates
Best Credit Repair Companies
Best Credit Cards
View All
Academy
Academy
Investing for Beginners
Trading for Beginners
Become a Day Trader
Technical Analysis
All Investing Courses
All Trading Courses
View All
Economy
Economy
Government and Policy
Monetary Policy
Fiscal Policy
Economics
View All
Financial Terms
Newsletter
About Us
Follow Us
Table of Contents
Expand
Table of Contents
What Is ERC-20?
History
Contents
Goals
BEP-2 vs. ERC-20
FAQs
The Bottom Line
Cryptocurrency
Altcoins
What Are ERC-20 Tokens on the Ethereum Network?
By
Nathan Reiff
Full Bio
Nathan Reiff has been writing expert articles and news about financial topics such as investing and trading, cryptocurrency, ETFs, and alternative investments on Investopedia since 2016.
Learn about our
editorial policies
Updated January 03, 2024
Reviewed by
Amilcar Chavarria
Reviewed by
Amilcar Chavarria
Full Bio
Amilcar has 10 years of FinTech, blockchain, and crypto startup experience and advises financial institutions, governments, regulators, and startups.
Learn about our
Financial Review Board
Fact checked by
Timothy Li
Fact checked by
Timothy Li
Full Bio
Timothy Li is a consultant, accountant, and finance manager with an MBA from USC and over 15 years of corporate finance experience. Timothy has helped provide CEOs and CFOs with deep-dive analytics, providing beautiful stories behind the numbers, graphs, and financial models.
Learn about our
editorial policies
Trending Videos
Close this video player
What Is ERC-20?
ERC-20 is the technical standard for fungible tokens created using the Ethereum blockchain. A fungible token is one that is exchangeable with another token, whereas the well-known ERC-721 non-fungible tokens (NFTs) are not.
ERC-20 allows developers to create smart-contract-enabled tokens that can be used with other products and services. These tokens are a representation of an asset, right, ownership, access, cryptocurrency, or anything else that is not unique in and of itself but can be transferred.
Key Takeaways
Ethereum Request for Comment 20 (ERC-20) is the implemented standard for fungible tokens created using the Ethereum blockchain.ERC-20 guides the creation of new tokens on the Ethereum blockchain so that they are interchangeable with other smart contract tokens.Since its implementation, most Ethereum-based tokens have been created using the ERC-20 standard.
History of ERC-20
Smart contracts were becoming more popular in 2015, but several issues needed to be addressed. Because anyone could make a token, many were being made. However, there wasn't a way to ensure that all the different tokens could be created, used, or exchanged by everyone using the blockchain. Without a standardized token methodology, every application would need its own token. Users would need to find a way to convert them back and forth between the hundreds of apps being developed.
How the Standard Started
ERC-20 was proposed by developer Fabian Vogelsteller in 2015 to address the need for a standard within smart contracts on the Ethereum blockchain. Vogelsteller submitted the proposal via the project's Github page as an Ethereum Request for Comment (ERC). As it was the twentieth comment, it was assigned the designation ERC-20.
Following the procedure used by the Ethereum developer community, the proposal was approved and implemented in 2017 as Ethereum Improvement Proposal 20 (EIP-20). However, it is still called ERC-20 because that's how it was known until it was approved.
In 2023, Ethereum altered how changes were suggested and processed for the ecosystem by splitting its method into two separate repositories. Ethereum Request for Comments (ERCs) were changed to address standardization and documentation for Ethereum's application layer. Ethereum Improvement Proposals became the method for suggesting, processing, and documenting changes for Ethereum itself.
Because the request was approved and implemented, smart contract tokens implemented on the Ethereum blockchain must conform to this standard if the developers want them to be interchangeable.
ERC-20 Contents
ERC-20 is a list of functions and events that must be implemented into a token for it to be considered ERC-20 compliant. These functions (called methods in the ERC) describe what must be included in the smart-contract-enabled token, while events describe an action. The functions a token must have are:
TotalSupply: The total number of tokens that will ever be issuedBalanceOf: The account balance of a token owner's accountTransfer: Automatically executes transfers of a specified number of tokens to a specified address for transactions using the tokenTransferFrom: Automatically executes transfers of a specified number of tokens from a specified address using the tokenApprove: Allows a spender to withdraw a set number of tokens from a specified account, up to a specific amountAllowance: Returns a set number of tokens from a spender to the owner
The events that must be included in the token are:
Transfer: An event triggered when a transfer is successfulApproval: A log of an approved event (an event)
The following functions are optional and are not required to be included, but they enhance the token's usability:
Token's name (optional)Its symbol (optional)Decimal points to use (optional)
"Token" and "Cryptocurrency" are often used interchangeably; all cryptocurrencies are tokens, but not all tokens are cryptocurrencies. Tokens often represent assets and rights that are external to a blockchain. Token, in the context of ERC-20 compliance, simply means a blockchain representation of something that meets the standards set by the Ethereum community to be considered a smart contract standard-compliant token.
So, what does this all mean? The functions and events are programming language, such as:
function name () public view returns (string)
function balanceOf (address _owner) public view returns (uint256 balance)
These functions provide a common structure for tokens so that they can be easily accessed, recognized, reviewed, and used. This reduces the confusion users and application developers would have if every token had different information contained within it. Additionally, the code functions assist in determining the number of tokens in circulation, storing and returning balances, making transfer and withdrawal requests, granting approval, and agreeing to automated transfers.
Plenty of well-known digital currencies use the ERC-20 standard. Some popular examples are:
Tether USD (USDT)
USD Coin (USDC)
Shiba Inu (SHIB)
Binance USD (BUSD)
BNB (BNB)
DAI Stablecoin (DAI)
HEX (HEX)
Bitfinex LEO (LEO)
Maker (MKR)
Goals of ERC-20
The ERC-20 standard has a vital role within the blockchain; it defines a standard list of rules that Ethereum tokens using smart contracts must adhere to. Some of these rules include how the tokens can be transferred, how transactions are approved, how users can access data about a token, and the total supply of tokens.
This compliance is also necessary for Ethereum to keep the promise of scalability; it ensures compatibility between the many different tokens created using the Ethereum ecosystem.
Consequently, this token standard empowers developers of all types to accurately predict how new tokens will function within the larger Ethereum system. This simplifies the task for developers; they can proceed with their work, knowing that every existing project won't need to be redone every time a new token is released. Additionally, new projects won't need to worry about compatibility with old projects as long as the token follows the rules.
Fortunately, most token developers have fallen in line with ERC-20 rules, meaning that most tokens released through Ethereum are ERC-20 compliant.
BEP-2 vs. ERC-20
ERC-20 is the standard for tokens in the Ethereum ecosystem. Many other tokens, blockchains, and ecosystems have derived from Ethereum. One such ecosystem and blockchain belongs to Binance, the cryptocurrency exchange. The team behind Binance created its own blockchain, the Binance Chain, from an Ethereum fork.
Binance developers then created a standard for tokens on their blockchain. This standard is called BEP-2 and is similar to ERC-20 in that it guides token creation for use on the Binance Chain.
Binance also has created a side chain that runs alongside the Binance Chain called the Binance Smart Chain. This chain is compatible with ERC-20 tokens, the Ethereum Virtual Machine, and the Binance Chain; however, it uses a newer standard called BEP-20, which creates cross-chain compatibility.
What Does ERC-20 Mean?
ERC-20 is Ethereum Request for Comment, number 20. ERC-20 is the standard for smart contract tokens created using Ethereum.
What's the Difference Between ETH and ERC-20?
Ether (ETH) is the native token used by the Ethereum blockchain and network as an internal payment system. ERC-20 is the standard for creating smart contract-enabled fungible tokens to be used in the Ethereum ecosystem.
What Is an ERC-20 Wallet?
An ERC-20 wallet is a wallet that lets you manage ERC-20 compliant tokens.
The Bottom Line
To address growing concerns that multiple tokens would not be transferrable on the Ethereum blockchain, a proposal for standards was made and implemented in 2015. Called Ethereum Request for Comment (ERC) 20, the standard guides token creation so that tokens compatible with the Ethereum blockchain are interchangeable.
The comments, opinions, and analyses expressed on Investopedia are for informational purposes only. Read our warranty and liability disclaimer for more info. As of the date this article was written, the author owns BTC and XRP.
Article Sources
Investopedia requires writers to use primary sources to support their work. These include white papers, government data, original reporting, and interviews with industry experts. We also reference original research from other reputable publishers where appropriate. You can learn more about the standards we follow in producing accurate, unbiased content in our
editorial policy.
Ethereum Improvment Proposals. "ERC-20:Token Standard."
Github. "Ethereum|ERCs."
Github. "Ethereum|EIPs."
Andreas M. Antonopoulos and Gavin Wood. "Mastering Ethereum," Page 227. O'Reilly Media, 2018.
Compare Accounts
Advertiser Disclosure
×
The offers that appear in this table are from partnerships from which Investopedia receives compensation. This compensation may impact how and where listings appear. Investopedia does not include all offers available in the marketplace.
Provider
Name
Description
Take the Next Step to Invest
Advertiser Disclosure
×
The offers that appear in this table are from partnerships from which Investopedia receives compensation. This compensation may impact how and where listings appear. Investopedia does not include all offers available in the marketplace.
Related Articles
What Crypto Users Need to Know: The ERC20 Standard
Non-Fungible Token (NFT): What It Means and How It Works
How to Create an NFT
Financial Advisor Guide to Initial Coin Offerings (ICOs)
Bancor: What it Means, Purpose, Criticisms
10 Important Cryptocurrencies Other Than Bitcoin
Partner Links
Related Terms
Non-Fungible Token (NFT): What It Means and How It Works
NFTs are cryptographic tokens that cannot be replicated. They can be used for transactions, have created new markets, and may have more use cases in the future.
more
Bancor: What it Means, Purpose, Criticisms
Bancor blockchain protocol allows users direct zero/low fee conversion between different crypto coins.
more
Chainlink: What It Is and How It Works
Chainlink (LINK) is a cryptocurrency and technology platform that enables blockchain platforms to securely interact with external data.
more
Binance Coin (BNB) Uses, Support, and Market Cap
Binance Coin (BNB) is the native currency of the Binance exchange which follows the ERC 20 standard.
more
What Are Native Tokens?
"Native token" is the term used to refer to a token created specifically for a blockchain. Many native tokens also become tradable on exchanges.
more
Hex (HEX): What It Is, History, and Concerns
Hex describes itself as a high-interest blockchain certificate of deposit. Users are rewarded for waiting to sell their HEX after set periods of time.
more
About Us
Terms of Service
Dictionary
Editorial Policy
Advertise
News
Privacy Policy
Contact Us
Careers
#
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
Investopedia is part of the Dotdash Meredith publishing family.
Please review our updated Terms of Service.