im钱包官方安卓版
数字资产服务平台

im钱包官方安卓版是全球著名的数字资产交易平台之一,主要面向全球用户提供比特币、莱特币、以太币等数字资产的币币和衍生品交易服务。

imtoken最新官方网|erc20转账需要多久

时间:2024-03-16 05:14:44

ERC20转账需要多久?ERC20转账时间介绍-211Coin

ERC20转账需要多久?ERC20转账时间介绍-211Coin

首页

7*24快讯

政策

新闻

币市要闻

矿业动态

区块链

百科

ERC20转账需要多久?ERC20转账时间介绍

来源:211COIN

2022-02-14 15:59:41

提到ERC20大多数投资者都不会陌生,它是以太坊区块链上的一种智能合约协议标准,相对于别的ERC标准,erc-20的解释较为麻烦,因为它算是许多标准的基础。ERC20与TRC20搞混这两个地址经常被投资者搞混,这两种链名称虽然相似,但是却有着很大的区别,其中ERC-20是最广为人知的标准,在ERC-20标准里没有价值的区别,数字货币之前是可以相互转换的。讲到这里大家可能就要问了,既然ERC20可以转账,那么ERC20转账需要多久?下面211Coin小编就给大家介绍一下ERC20转账时间。

ERC20转账时间介绍

USDT-ERC20是Tether泰达公司基于ETH网络发行的USDT,充币地址是ETH地址,充提币走ETH网络。USDT-ERC20使用的是ERC20协议。

2018年初,以太坊网络爆红,智能合约普及于区块链应用,ERC20-USDT出现。和Omni-USDT一样,使用ERC20-USDT同样需要支付旷工费,但转账速度有了显著的提升。由于安全性好、转账速度快,ERC20-USDT被市场广泛接受,USDT的发行者泰达公司也开始放弃了比特币Omni,转而支持更高效的以太坊ERC20。

随着近期泰达公司多次在以太坊上增发USDT,ERC20-USDT的数量显著增加,目前已超过Omni-USDT总量的50%。除了官方放弃Omni协议以外,主流交易所也开始转向支持ERC20-USDT。7月3日,币安交易所宣布将由OMNI网络切换为ERC20网络,虽然原OMNI网络的USDT可以继续充值并上账,但将无法提现OMNI网络的USDT。

除了地址不同之外,选择不同的链类型,转转账的速度和手续费也是不一样的。如果你希望可以快速转账,追求的是速度,那就应该选择波场区块链的TRC20链类型。波场网络TPS达到1500TPS,目前来说转账最快到账的是波场USDT。

如果你在意的是手续费,希望转账手续费能低一些,那也应该选择TRC20链类型。因为TRC20链类型转账,手续费为0。而ERC20链类型的手续费是2USDT,大概是14块钱。OMIN链类型手续费最贵,需要5个USDT,大概是35人民币。

但是如果你希望转账能安全一点,那就选择比特币网络的OMIN链类型,这个链类型虽然手续费高了一点,但是安全性好。贵,也是有道理的嘛。

ERC20特点汇总

1、支付的手续费种类为ETH

ERC-USDT与其他以太坊上的Token一样,存储在以太坊地址上,因此每次转账的时候,需要支付的手续费种类为ETH。地址示例:0xdac17f958d2ee523a2206206994597c13d831ec7(ERC-20合约)

2、大部分交易所均支持充提,提币限额较低

基本上主流交易所都支持ERC-USDT充提,在提币时可以选择是提到BTC地址还是ETH地址。并且,以火币为例,ERC-USDT的最小提币限额(2USDT)目前是小于Omni-USDT(200USDT)的。

3、支持智能合约,链上交易查询更便捷

与Omni-USDT不同的是,ERC-USDT可以支持智能合约。在主流以太坊浏览器内均可以查询到ERC-20的USDT交易,感兴趣的用户可以去Tokenview的以太坊浏览器查询ERC-USDT的交易详情。

ERC20到底是什么?

在Ethereum中,代币几乎可以代表任何东西,从在线平台的信誉点、游戏中角色的技能、彩票到金融资产债券,再到真正的商品,如公司的股份、货币、金盎司等!如此强大的功能,值得也必须处理好。如此强大的功能,理应也必须由一个强大的标准来处理,对吗?这正是ERC-20的作用所在,ERC-20就是针对这些发布的Token(代币)制定的一个固定的基础的标准原则。

截至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便可参与这些项目。

上述内容就是对ERC20转账需要多久?这个问题的解答,ERC20转账时间并不确定,与各方面因素都有关系,遇到网络拥堵的话到账时间也会更慢一些。ERC-20是关于如何构建以太坊代币的API规范。它是一种社区采用的标准,允许在各种用例中支持代币,并且ERC-20代币可以多种方式分发,其中一种流行的方法是ICO。ICO是项目团队通过创建自己的ERC-20代币来为其业务开发筹集资金的一种方式,该代币可以由以太币的投资者购买。

ERC20

211COIN发布此信息目的在于传播更多信息,与本网站立场无关,文章内容仅供参考,不代表任何确定性判断,且不构成投资建议,请谨慎对待,风险自担。

首页 > 百科 > 链知识 > ERC20转账需要多久?ERC20转账时间介绍

好文章,需要你的鼓励

相关阅读

链上转账多久到账?链上转账到账时间介绍

ERC20协议地址是什么意思?ERC20协议地址介绍

冷钱包如何转账?冷钱包转账需要网络吗?

ERC20是什么链?ERC20链名称是什么?

TRC20和ERC20能互转吗?TRC20和ERC20哪个快?

ETH和ERC20是一条链吗?ETH和ERC20的地址一样吗

一周热文

更多>

1

METO币是什么币?METO币怎么样?

211COIN

2

比特币V转站回6.6万美元、以太坊强势突破3900美元创2年新高!

211COIN

3

WISE币是什么币?一文了解WISE币

211COIN

4

Starknet链ZKX推出OG Trade、Pro Trade:可获取ZKX、STRK奖励!

211COIN

5

加密货币转账匿名交易违法吗?

211COIN

24H热文

更多>

1

比特币V转站回6.6万美元、以太坊强势突破3900美元创2年新高!

3504

2

WISE币是什么币?一文了解WISE币

3494

3

加密货币转账匿名交易违法吗?

3486

4

币安新币挖矿项目衍生品交易所AEVO是什么?为何拉动BBN暴涨

3472

5

坎昆升级助推L2涨势?STRK、OP大涨超30%!

3466

微信:yelbtc 请注明来意

|

邮箱:biquanzi@foxmail.com

Copyright © 2018-2022 211COIN版权所有.

京ICP备17000885号-3

返回顶部

USDT中omni和erc20、trc20的对比转账到账时间和安全性等对比 - 知乎

USDT中omni和erc20、trc20的对比转账到账时间和安全性等对比 - 知乎首发于币圈老王切换模式写文章登录/注册USDT中omni和erc20、trc20的对比转账到账时间和安全性等对比币圈老王专注科技金融,在这给你带来链圈、币圈 最新鲜、最有价值的咨讯OMNI、ERC20和波场三种USDT的科普扫盲以及充错USDT的应对方法:此前我们介绍和科普过Omni、ERC-20以及波场上几种USDT区别,知道了哪种转账快、手续费低、安全。但确实不够直观,我们又重新整理了一遍进行科普扫盲:第一种 OMNI协议地址样式 :数字1或者3开头 例:13yC9Mk....使用网络:比特币网络网络拥堵情况:偶尔拥堵日常转账速度:慢(0.6-2小时不等)手续费: 最高,转账搜续费一般和BTC一致,平台提现一般收2-20USDT不等"安全性:最高使用建议:大额低频走比特币网络第二种 ERC20协议地址样式:数字0和小写x开头 例:0xbdcgu9hsksd....使用网络:以太坊网络网络拥堵情况: 经常拥堵 日常转账速度 中等 (几分钟到数十分钟)手续费: 一般,钱包转账手续费与转ETH一致,平台提现一般收1-5USDT不等安全性:高使用建议:中等额度走ETH网络第三种 TRC20协议地址样式:(谨防充错)大写字母T开头 例:T9zP14nMt....使用网络: 波场网络网络拥堵情况: 暂时基本不拥堵日常转账速度 :快(几秒到几分钟)手续费:无,钱包转账0手续费,平台提现时有可能收取少量手续费"安全性: 低于前两者使用建议 小额高频走波场网络平台充USDT错到BTC、ETH、TRX的充值地址时的补救方法: 只能找相应的平台客服,部分平台可找回。还有一种充错情况,若充到不支持ERC20\TRC20的USDT的交易平台的ETH或者TRX地址内时,或许需要等待该平台上线相应种类协议USDT后方可提取发布于 2019-06-23 02:11​赞同 14​​3 条评论​分享​喜欢​收藏​申请转载​文章被以下专栏收录币

USDT提现要多久到账?TRC20和ERC20等几种USDT的转账时间 - 白话区块链

USDT提现要多久到账?TRC20和ERC20等几种USDT的转账时间 - 白话区块链

风险提示:防范以虚拟货币/区块链名义进行的非法集资风险。 ——银保监会等五部门

search

资讯

快讯

科普

专栏

search

mobile

白话区块链

区块链世界入口第一站,人人都能看懂

的区块链;24 小时热点实时追踪。

wechat

微信公众号

扫码关注

Hellobtc

USDT提现要多久到账?TRC20和ERC20等几种USDT的转账时间

白话区块链

2019-11-04 15:17:25

微信分享

扫码分享

关于USDT提现、转账的到账时间要多久? USDT提现卡在路上了要找谁?

作者:大白 / 来源:白话区块链

许多人都遇到过USDT提现、转账被“卡”住的情况,有时候比较焦急,特别想知道到底什么时候到账,本文将介绍几种不同协议的USDT到账时间的预估:

 01 

正常USDT转账到账时间情况

Omni的USDT:因为走的是比特币网络,所以到账时间稍微慢一点,常规需要30-60分钟以上才会显示到账

ERC20的USDT:因为走以太坊网络,和以太坊Token转账时间一致,常规在10-20分钟左右显示到账

TRC20的USDT:走的是波场网络,和波场转账时间一致,常规是5分钟以内到账

 

 02 

为什么很长时间都还没到?

主要问题是卡在流程上了

先了解一下USDT提现和转账的流程,当我们在交易平台或者托管钱包等发起一笔USDT提现时的流程是:转出审核==》发出交易广播==》入账审核==》确认入账

1.卡在转出审核:提现或者转出一笔USDT,经历上面的3个环节都由可能会卡住,通常提出的平台的风控机制影响,越大金额的USDT提现等待时间可能会越长。这个流程里出问题找转出平台客服。

2.卡在交易广播:通过转出审核后,交易被广播到了对应的区块链网络上这时候,就可以等待出块节点打包了,很快会在对应得浏览器上查询到这笔交易(平台会给出交易tx哈希值),这个流程卡住了,比如网络拥堵,没有客服可以找,只能等。

3.卡在入账审核:为了防止双花和非法资金流入,一般平台也会设置入账审核(交易被打包后若干个确认后审核),也是金额越大时间可能越长一些,小额机器自动审核,大额的人工审核,这个流程出问题就找入账交易平台客服即可。

因此,USDT提现多久到账需要根据这笔状态来查询判断该笔转账到了哪一个流程出问题就找哪一边客服处理,或者说耐心等待。

USDT   TRC20   ERC20   到账时间

白话推荐阅读

USDT面临严重抛压,是做市商们在退出吗? 06-15 16:03买卖 USDT 是犯法?实践中要注意哪些风险? 06-07 13:25季入7亿美金!看USDT闷声发大财就知道稳定币赛道为何 04-19 12:20波场DAO新物种下场 USDD如何破局稳定币市场 04-22 13:56USDT暴雷担忧逐渐隐去,一年增长10倍的稳定币市场格局 07-08 23:34USDT等美元稳定币已成美国金融结算基础设施:一文说透 01-21 13:13

NFT进入主流市场突破性的一年,顶级拍卖行苏富比的NFT拍 01-10 14:49加密市场将面临的监管有多严厉?FATF发布相关监管指南解 06-26 11:14

白话区块链

区块链世界入口第一站,人人都能看懂的区块链

消除无知 拯救恐慌,灯火教育做真正的区 第16的COSMOS ATOM跨链是区块链未来的 怎么看EOS堵塞这件事,你还相信EOS会是 数字资产理财方式越发多样,普通人没有 区块链书籍推荐:10本通俗讲解的入门书

白话区块链

区块链世界入口第一站,人人都能看懂的区块链;24 小时热点实时追踪。

热门文章

为什么现在没什么人谈「区块链」了

08-02 14:24

破坏区块链项目团队长期战略的方式

06-07 10:49

三种基于以太坊LST建立的稳定币协

06-06 19:29

万字长文|15个加密赛道发展现状与趋

05-19 11:59

Facebook等大厂超十亿用户数据遭泄

07-04 13:21

元宇宙的起源:虚拟世界进化史

03-25 14:00

摩根大通元宇宙报告:打工人与企业

02-18 16:05

马斯克预言2022经济危机,我们如何为

01-17 15:51

区块链红利吃饱后,这个巨头又想征服

12-27 22:22

元宇宙是不是骗局咱不知道,但骗子来

12-21 15:07

微信公众号

扫码关注

Hellobtc

关于我们

关于白话区块链

用户协议

免责声明

加入我们

隐私条款

服务联系

白话区块链入门

公众号

© 2017 ~ 2020 南京链上网络科技有限公司 版权所有 苏ICP备17074177号-1

ERC20转账需要多久?ERC20转账时间介绍-211Coin

ERC20转账需要多久?ERC20转账时间介绍-211Coin

首页

7*24快讯

政策

新闻

币市要闻

矿业动态

区块链

百科

ERC20转账需要多久?ERC20转账时间介绍

来源:211COIN

2022-02-14 15:59:41

提到ERC20大多数投资者都不会陌生,它是以太坊区块链上的一种智能合约协议标准,相对于别的ERC标准,erc-20的解释较为麻烦,因为它算是许多标准的基础。ERC20与TRC20搞混这两个地址经常被投资者搞混,这两种链名称虽然相似,但是却有着很大的区别,其中ERC-20是最广为人知的标准,在ERC-20标准里没有价值的区别,数字货币之前是可以相互转换的。讲到这里大家可能就要问了,既然ERC20可以转账,那么ERC20转账需要多久?下面211Coin小编就给大家介绍一下ERC20转账时间。

ERC20转账时间介绍

USDT-ERC20是Tether泰达公司基于ETH网络发行的USDT,充币地址是ETH地址,充提币走ETH网络。USDT-ERC20使用的是ERC20协议。

2018年初,以太坊网络爆红,智能合约普及于区块链应用,ERC20-USDT出现。和Omni-USDT一样,使用ERC20-USDT同样需要支付旷工费,但转账速度有了显著的提升。由于安全性好、转账速度快,ERC20-USDT被市场广泛接受,USDT的发行者泰达公司也开始放弃了比特币Omni,转而支持更高效的以太坊ERC20。

随着近期泰达公司多次在以太坊上增发USDT,ERC20-USDT的数量显著增加,目前已超过Omni-USDT总量的50%。除了官方放弃Omni协议以外,主流交易所也开始转向支持ERC20-USDT。7月3日,币安交易所宣布将由OMNI网络切换为ERC20网络,虽然原OMNI网络的USDT可以继续充值并上账,但将无法提现OMNI网络的USDT。

除了地址不同之外,选择不同的链类型,转转账的速度和手续费也是不一样的。如果你希望可以快速转账,追求的是速度,那就应该选择波场区块链的TRC20链类型。波场网络TPS达到1500TPS,目前来说转账最快到账的是波场USDT。

如果你在意的是手续费,希望转账手续费能低一些,那也应该选择TRC20链类型。因为TRC20链类型转账,手续费为0。而ERC20链类型的手续费是2USDT,大概是14块钱。OMIN链类型手续费最贵,需要5个USDT,大概是35人民币。

但是如果你希望转账能安全一点,那就选择比特币网络的OMIN链类型,这个链类型虽然手续费高了一点,但是安全性好。贵,也是有道理的嘛。

ERC20特点汇总

1、支付的手续费种类为ETH

ERC-USDT与其他以太坊上的Token一样,存储在以太坊地址上,因此每次转账的时候,需要支付的手续费种类为ETH。地址示例:0xdac17f958d2ee523a2206206994597c13d831ec7(ERC-20合约)

2、大部分交易所均支持充提,提币限额较低

基本上主流交易所都支持ERC-USDT充提,在提币时可以选择是提到BTC地址还是ETH地址。并且,以火币为例,ERC-USDT的最小提币限额(2USDT)目前是小于Omni-USDT(200USDT)的。

3、支持智能合约,链上交易查询更便捷

与Omni-USDT不同的是,ERC-USDT可以支持智能合约。在主流以太坊浏览器内均可以查询到ERC-20的USDT交易,感兴趣的用户可以去Tokenview的以太坊浏览器查询ERC-USDT的交易详情。

ERC20到底是什么?

在Ethereum中,代币几乎可以代表任何东西,从在线平台的信誉点、游戏中角色的技能、彩票到金融资产债券,再到真正的商品,如公司的股份、货币、金盎司等!如此强大的功能,值得也必须处理好。如此强大的功能,理应也必须由一个强大的标准来处理,对吗?这正是ERC-20的作用所在,ERC-20就是针对这些发布的Token(代币)制定的一个固定的基础的标准原则。

截至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便可参与这些项目。

上述内容就是对ERC20转账需要多久?这个问题的解答,ERC20转账时间并不确定,与各方面因素都有关系,遇到网络拥堵的话到账时间也会更慢一些。ERC-20是关于如何构建以太坊代币的API规范。它是一种社区采用的标准,允许在各种用例中支持代币,并且ERC-20代币可以多种方式分发,其中一种流行的方法是ICO。ICO是项目团队通过创建自己的ERC-20代币来为其业务开发筹集资金的一种方式,该代币可以由以太币的投资者购买。

ERC20

211COIN发布此信息目的在于传播更多信息,与本网站立场无关,文章内容仅供参考,不代表任何确定性判断,且不构成投资建议,请谨慎对待,风险自担。

首页 > 百科 > 链知识 > ERC20转账需要多久?ERC20转账时间介绍

好文章,需要你的鼓励

相关阅读

链上转账多久到账?链上转账到账时间介绍

ERC20协议地址是什么意思?ERC20协议地址介绍

冷钱包如何转账?冷钱包转账需要网络吗?

ERC20是什么链?ERC20链名称是什么?

TRC20和ERC20能互转吗?TRC20和ERC20哪个快?

ETH和ERC20是一条链吗?ETH和ERC20的地址一样吗

一周热文

更多>

1

METO币是什么币?METO币怎么样?

211COIN

2

比特币V转站回6.6万美元、以太坊强势突破3900美元创2年新高!

211COIN

3

WISE币是什么币?一文了解WISE币

211COIN

4

Starknet链ZKX推出OG Trade、Pro Trade:可获取ZKX、STRK奖励!

211COIN

5

加密货币转账匿名交易违法吗?

211COIN

24H热文

更多>

1

比特币V转站回6.6万美元、以太坊强势突破3900美元创2年新高!

3504

2

WISE币是什么币?一文了解WISE币

3494

3

加密货币转账匿名交易违法吗?

3486

4

币安新币挖矿项目衍生品交易所AEVO是什么?为何拉动BBN暴涨

3472

5

坎昆升级助推L2涨势?STRK、OP大涨超30%!

3466

微信:yelbtc 请注明来意

|

邮箱:biquanzi@foxmail.com

Copyright © 2018-2022 211COIN版权所有.

京ICP备17000885号-3

返回顶部

Just a moment...

a moment...Enable JavaScript and cookies to conti

代币转账 · Ethereum Development with Go

代币转账 · Ethereum Development with Go

Introduction

客户端

创建客户端

以太坊账户

账户余额

账户代币余额

生成新钱包

密匙库

分层确定性钱包

地址验证

交易

查询区块

查询交易

ETH转账

代币转账

监听新区块

创建裸交易

发送裸交易

智能合约

智能合约 & ABI

部署智能合约

加载智能合约

查询智能合约

写入智能合约

读取智能合约二进制码

查询ERC20代币智能合约

事件日志

监听事件日志

读取事件日志

读取ERC20代币的事件日志

读取0x Protocol事件日志

签名

生成签名

验证签名

测试

发币龙头

使用模拟客户端

Swarm存储

创建 Swarm存储

上传文件到Swarm

从Swarm下载文件

Whisper通信协议

创建Whisper客户端

生成Whisper密匙对

在Whisper上发送消息

监听Whisper消息

工具

工具集合

专有词汇表

资源

本書使用 GitBook 釋出

代币转账

代币的转账

本节将向你介绍如何转移ERC-20代币。了解如何转移非ERC-20兼容的其他类型的代币请查阅智能合约的章节 来了解如何与智能合约交互。

假设您已连接客户端,加载私钥并配置燃气价格,下一步是设置具体的交易数据字段。 如果你完全不明白我刚讲的这些,请先复习 以太币转账的章节。

代币传输不需要传输ETH,因此将交易“值”设置为“0”。

value := big.NewInt(0)

先将您要发送代币的地址存储在变量中。

toAddress := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d")

现在轮到有趣的部分。 我们需要弄清楚交易的 data 部分。 这意味着我们需要找出我们将要调用的智能合约函数名,以及函数将接收的输入。 然后我们使用函数名的keccak-256哈希来检索 方法ID,它是前8个字符(4个字节)。 然后,我们附加我们发送的地址,并附加我们打算转账的代币数量。 这些输入需要256位长(32字节)并填充左侧。 方法ID不需填充。

为了演示,我创造了一个新的代币(HelloToken HTN),这个可以用代币工厂服务来完成https://tokenfactory.surge.sh, 代币我部署到了Rinkeby测试网。

让我们将代币合约地址分配给变量。

tokenAddress := common.HexToAddress("0x28b149020d2152179873ec60bed6bf7cd705775d")

函数名将是传递函数的名称,即ERC-20规范中的transfer和参数类型。 第一个参数类型是address(令牌的接收者),第二个类型是uint256(要发送的代币数量)。 不需要没有空格和参数名称。 我们还需要用字节切片格式。

transferFnSignature := []byte("transfer(address,uint256)")

我们现在将从go-ethereum导入crypto/sha3包以生成函数签名的Keccak256哈希。 然后我们只使用前4个字节来获取方法ID。

hash := sha3.NewKeccak256()

hash.Write(transferFnSignature)

methodID := hash.Sum(nil)[:4]

fmt.Println(hexutil.Encode(methodID)) // 0xa9059cbb

接下来,我们需要将给我们发送代币的地址左填充到32字节。

paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32)

fmt.Println(hexutil.Encode(paddedAddress)) // 0x0000000000000000000000004592d8f8d7b001e72cb26a73e4fa1806a51ac79d

接下来我们确定要发送多少个代币,在这个例子里是1,000个,并且我们需要在big.Int中格式化为wei。

amount := new(big.Int)

amount.SetString("1000000000000000000000", 10) // 1000 tokens

代币量也需要左填充到32个字节。

paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)

fmt.Println(hexutil.Encode(paddedAmount)) // 0x00000000000000000000000000000000000000000000003635c9adc5dea00000

接下来我们只需将方法ID,填充后的地址和填后的转账量,接到将成为我们数据字段的字节片。

var data []byte

data = append(data, methodID...)

data = append(data, paddedAddress...)

data = append(data, paddedAmount...)

燃气上限制将取决于交易数据的大小和智能合约必须执行的计算步骤。 幸运的是,客户端提供了EstimateGas方法,它可以为我们估算所需的燃气量。 这个函数从ethereum包中获取CallMsg结构,我们在其中指定数据和地址。 它将返回我们估算的完成交易所需的估计燃气上限。

gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{

To: &toAddress,

Data: data,

})

if err != nil {

log.Fatal(err)

}

fmt.Println(gasLimit) // 23256

接下来我们需要做的是构建交易事务类型,这类似于您在ETH转账部分中看到的,除了to字段将是代币智能合约地址。 这个常让人困惑。我们还必须在调用中包含0 ETH的值字段和刚刚生成的数据字节。

tx := types.NewTransaction(nonce, tokenAddress, value, gasLimit, gasPrice, data)

下一步是使用发件人的私钥对事务进行签名。 SignTx方法需要EIP155签名器(EIP155 signer),这需要我们从客户端拿到链ID。

chainID, err := client.NetworkID(context.Background())

if err != nil {

log.Fatal(err)

}

signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)

if err != nil {

log.Fatal(err)

}

最后广播交易。

err = client.SendTransaction(context.Background(), signedTx)

if err != nil {

log.Fatal(err)

}

fmt.Printf("tx sent: %s", signedTx.Hash().Hex()) // tx sent: 0xa56316b637a94c4cc0331c73ef26389d6c097506d581073f927275e7a6ece0bc

你可以去Etherscan看交易的确认过程: https://rinkeby.etherscan.io/tx/0xa56316b637a94c4cc0331c73ef26389d6c097506d581073f927275e7a6ece0bc

要了解更多如何加载ERC20智能合约并与之互动的内容,可以查看ERC20代币的智能合约章节.

完整代码

transfer_tokens.go

package main

import (

"context"

"crypto/ecdsa"

"fmt"

"log"

"math/big"

"github.com/ethereum/go-ethereum"

"github.com/ethereum/go-ethereum/common"

"github.com/ethereum/go-ethereum/common/hexutil"

"github.com/ethereum/go-ethereum/core/types"

"github.com/ethereum/go-ethereum/crypto"

"github.com/ethereum/go-ethereum/crypto/sha3"

"github.com/ethereum/go-ethereum/ethclient"

)

func main() {

client, err := ethclient.Dial("https://rinkeby.infura.io")

if err != nil {

log.Fatal(err)

}

privateKey, err := crypto.HexToECDSA("fad9c8855b740a0b7ed4c221dbad0f33a83a49cad6b3fe8d5817ac83d38b6a19")

if err != nil {

log.Fatal(err)

}

publicKey := privateKey.Public()

publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)

if !ok {

log.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")

}

fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)

nonce, err := client.PendingNonceAt(context.Background(), fromAddress)

if err != nil {

log.Fatal(err)

}

value := big.NewInt(0) // in wei (0 eth)

gasPrice, err := client.SuggestGasPrice(context.Background())

if err != nil {

log.Fatal(err)

}

toAddress := common.HexToAddress("0x4592d8f8d7b001e72cb26a73e4fa1806a51ac79d")

tokenAddress := common.HexToAddress("0x28b149020d2152179873ec60bed6bf7cd705775d")

transferFnSignature := []byte("transfer(address,uint256)")

hash := sha3.NewKeccak256()

hash.Write(transferFnSignature)

methodID := hash.Sum(nil)[:4]

fmt.Println(hexutil.Encode(methodID)) // 0xa9059cbb

paddedAddress := common.LeftPadBytes(toAddress.Bytes(), 32)

fmt.Println(hexutil.Encode(paddedAddress)) // 0x0000000000000000000000004592d8f8d7b001e72cb26a73e4fa1806a51ac79d

amount := new(big.Int)

amount.SetString("1000000000000000000000", 10) // 1000 tokens

paddedAmount := common.LeftPadBytes(amount.Bytes(), 32)

fmt.Println(hexutil.Encode(paddedAmount)) // 0x00000000000000000000000000000000000000000000003635c9adc5dea00000

var data []byte

data = append(data, methodID...)

data = append(data, paddedAddress...)

data = append(data, paddedAmount...)

gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{

To: &toAddress,

Data: data,

})

if err != nil {

log.Fatal(err)

}

fmt.Println(gasLimit) // 23256

tx := types.NewTransaction(nonce, tokenAddress, value, gasLimit, gasPrice, data)

chainID, err := client.NetworkID(context.Background())

if err != nil {

log.Fatal(err)

}

signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)

if err != nil {

log.Fatal(err)

}

err = client.SendTransaction(context.Background(), signedTx)

if err != nil {

log.Fatal(err)

}

fmt.Printf("tx sent: %s", signedTx.Hash().Hex()) // tx sent: 0xa56316b637a94c4cc0331c73ef26389d6c097506d581073f927275e7a6ece0bc

}

results matching ""

No results matching ""

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: 59009

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

什么是ERC20?以太坊代币标准指南

什么是ERC20?以太坊代币标准指南

产品

加密支付网关

彻底改变支付方式

加密钱包

保护数字资产

加密货币发票

轻松的计费解决方案

批量支付

简化批量传输

White Label

定制品牌解决方案

Donations

通过加密货币增强捐赠能力

连接

API

整合与创新

整合解决方案

优化的插件和库以实现平滑集成

学习

博客

见解和更新

常问问题

澄清您的疑问

帮助

支持与指导

公司

安全

保护您的数字资产

漏洞赏金

奖励安全研究

联系我们

寻求帮助

价钱

登录

报名

什么是ERC20?以太坊代币标准指南

发表于 Feb 8, 2024

分享到

ERC20 是在以太坊区块链上制定和部署智能合约的关键标准,是该生态系统中数字化代币的支柱。源于以太坊托管智能合约的能力——自动执行合约,协议条款直接写入代码行——ERC20 代币是以太坊功能的基石。这些代币支持创建各种去中心化应用程序 (dApp)和平台,从实用代币到去中心化金融 (DeFi)解决方案,所有这些都遵循 ERC20 准则以确保网络兼容性。以太坊是世界领先的可编程区块链,允许用户利用其技术铸造自己的代币,这些代币可以体现各种资产或权利,例如数字积分、公司股票,甚至法定货币的数字表示形式。 ERC20 标准概述了一组规则,确保这些代币在以太坊生态系统中无缝集成和运行,从而促进不同应用程序和服务之间的互操作性和功能。 ERC-20 是什么意思? ERC-20 标准是以太坊区块链上可替代代币创建的基石,由以太坊开发者Fabian Vogelsteller于 2015 年 11 月 19 日提出。该技术规范的正式名称为以太坊征求意见20 (ERC-20),为在以太坊生态系统中发行、创建和部署可互换代币奠定了基础。名称“ERC”表示开发人员建议增强区块链的方法,“20”标记专用于这套操作规则的具体提案编号。 Fungible token 的特点是能够在一对一的基础上无区别地进行交换,已广泛采用 ERC-20 标准,这表明它在以太坊网络上数十万个合约的扩散和运行中发挥着关键作用。该标准不仅促进了代币创建的统一方法,而且还通过为开发人员提供强大的框架来刺激以太坊平台的发展。 ERC-20 作为以太坊改进协议(称为 EIP-20)的认可和正式采用发生在 2017 年底。EIP-20 由 Vogelsteller 和以太坊联合创始人Vitalik Buterin共同撰写,EIP-20 的认可巩固了其作为重要协议的地位。以太坊区块链中的协议,支撑了大量可替代代币,这些代币已成为平台生态系统和更广泛的区块链社区不可或缺的一部分。 ERC-20 的工作原理ERC-20 标准为以太坊区块链上的加密代币功能制定了一个全面的框架,将操作分类为 getter、函数和事件,以确保生态系统内集成的一致性和易用性。 Getters 的目的是在不改变区块链状态的情况下检索和显示数据。 ERC-20 中概述的主要吸气剂包括:总供应量:此函数报告已发行的代币总数,提供对特定代币流通规模的深入了解。 Balance Of :返回特定账户的代币余额,让用户轻松验证其持有情况。津贴:这一独特功能促进了委托支出,其中一个账户可以授权另一个账户代表其支出指定的代币金额。例如,如果用户 A 授权用户 B 使用 50 个代币,则用户 B 可以使用这些代币进行交易,最多可达分配的金额,但不能超过。函数是面向操作的命令,可实现代币管理和传输:转账:这一核心功能用于将代币从一个账户转移到另一个账户,这是代币流通的一个基本方面。批准:它允许代币持有者指定另一个帐户的支出限额,从而实现以太坊网络内的自动支付和津贴等场景。转账来源:基于“批准”功能,允许第三方在批准的限额内在账户之间转移代币,从而简化涉及多方的交易。事件是智能合约发出的信号,表明已发生重大操作,提供透明度和可追溯性:转移事件:每当转移代币时都会触发该事件,该事件会记录交易,提供代币移动的可见性和验证。批准事件:当一个帐户批准另一个帐户花费特定代币金额时,会发出此事件,作为对委托权限的公开确认。除了核心功能之外,值得注意的是 ERC-20 在促进以太坊上去中心化应用程序 (dApp) 之间的互操作性方面的重要性。通过遵守一套标准化规则,ERC-20 代币可以轻松集成到钱包、交易所和其他 dApp 中,从而增强整个生态系统的流动性和实用性。此外,该标准为创新的金融应用程序和协议铺平了道路,通过支持从简单的转账到复杂的智能合约执行等广泛的交易,为去中心化金融(DeFi)的发展做出了重大贡献。作为其基础作用的证明,ERC-20 标准继续影响新代币标准和区块链技术的开发,突显其对以太坊区块链和更广泛的加密领域的关键影响。创建 ERC-20 代币ERC-20 代币通过在以太坊区块链上部署智能合约而存在。这些嵌入了自动执行代码的合约为代币创建和分配开辟了可能性领域,反映了传统金融机制的某些方面,但又具有创新性。一个说明性的场景涉及一个智能合约,旨在接受上限数量的以太坊,例如 10 ETH。收到 ETH 后,合约会激活其代币铸造功能,直接向贡献者的钱包发行预定义数量的代币(例如,每个 ETH 100 个代币)。这种机制可以有效地生成 100,000 个假设的“ABC”代币,并将它们分散给参与者以换取他们的以太坊贡献。这种方法类似于股票市场中首次公开募股(IPO)的概念,即公司向公众发行股票以换取投资资本。同样,智能合约的代币发行过程充当筹集资金的去中心化变体,投资者收到代币而不是股票。这种方法不仅通过消除中央机构实现投资民主化,而且还引入了一种在数字生态系统内资助项目和分配资产的新方式。除了筹款之外,ERC-20 代币标准还促进了各种应用程序,从在去中心化自治组织 (DAO)中授予投票权的治理代币到提供平台内服务访问权限的实用代币。智能合约的可编程特性允许实现限时释放、股息分配和自动奖励等创造性功能,通过灵活和创新的金融工具丰富生态系统。什么是天然气?在以太坊区块链生态系统中,“gas”表示用于量化进行交易或执行智能合约所需的计算量的计量单位。用“ gwei ”表示——以太坊原生加密货币以太币(ETH)的较小面额,通常等同于 nanoeth——气体充当将资源分配给以太坊虚拟机(EVM)的媒介。这种分配有利于去中心化应用程序的自主运行,包括以安全和去中心化的方式执行智能合约。天然气成本是通过供应和需求的动态相互作用来确定的,其中包括提供交易处理和智能合约执行所需计算能力的矿工,以及寻求这些处理能力的网络用户。如果提供的 Gas 价格未能符合其运营成本预期,矿工可以自行决定拒绝交易,从而建立一个 Gas 价格根据网络活动水平和矿工需求波动的市场。该机制通过防止垃圾邮件交易并将资源分配给那些愿意为计算服务支付市场价格的人来确保以太坊网络保持高效。它还强调了以太坊的去中心化性质,其中交易和智能合约的执行是通过平衡网络参与者的需求与矿工的运营能力的系统来激励的。 ERC-20 代币的种类ERC-20 代币通过提供通用且标准化的代币创建框架,彻底改变了以太坊区块链,支持跨不同领域的广泛应用。这些代币可以代表一切,从类似于公司股票的金融资产(在某些司法管辖区可能作为证券进行监管)到忠诚奖励和黄金或房地产等实物资产。例如,一些 ERC-20 代币的运作方式与公司股票类似,根据监管角度,其发行人可能需要承担特定的法律义务。另一些则在数字生态系统中提供创新的实用性,例如来自在线预订平台的忠诚度积分,可用于未来的服务或与其他人进行交易,从而在其原始背景之外增加一层价值和实用性。这种多功能性延伸到了像 Tether (USDT) 这样的稳定币,它们与现实世界的货币挂钩,并提供传统货币的数字对应物,并具有区块链技术的额外优势,例如易于转移和通过智能合约产生潜在收益。然而,用 ERC-20 代币代表物理对象或法定货币会带来挑战,特别是在维持数字到物理链接的准确性方面。例如,USDT 的价值与 Tether Limited 持有的美元挂钩,需要信任传统的审计方法以确保支持的存在,这凸显了数字领域和物理领域之间潜在的脱节。 ERC-20 代币的采用进一步体现在它们与各种应用程序的集成: 美元硬币 (USDC) 和 Tether (USDT) 等稳定币为加密市场提供了稳定性。治理代币,例如 Maker (MKR),可以参与去中心化决策。实用令牌授予对特定服务的访问权限,例如 Brave 浏览器中的基本注意令牌 (BAT) 。资产支持代币将数字代币与现实世界的资产联系起来,提供有形的价值。游戏内货币和Metaverse 平台利用 ERC-20 代币来管理虚拟经济并促进数字世界中的交易。去中心化金融 (DeFi)应用程序使用Aave (AAVE)等代币来实现治理和实用目的。成功的 ERC-20 代币,包括Uniswap (UNI) 、ApeCoin (APE)、 Wrapped Bitcoin (WBTC)和 Chainlink (LINK),展示了该标准的适应性及其在以太坊生态系统内促进创新方面的作用。这些代币具有多种功能,从促进数字社区内的去中心化交易和治理,到在DeFi应用程序中使用比特币,以及将智能合约与外部数据连接起来。 ERC-20 代币的广泛采用和成功凸显了促进整个以太坊网络兼容性和互操作性的统一标准的重要性。这种标准化对于使区块链技术超越那些具有深厚技术知识的人来说至关重要,为数字代币继续丰富数字世界和物理世界的未来铺平了道路。 ERC-20、ERC-721、ERC-1155以太坊区块链支持各种代币标准,每个标准旨在满足生态系统内的不同需求。除了众所周知的 ERC-20 标准之外,另外两个重要标准是 ERC-721 和 ERC-1155,它们扩展了可以在区块链上表示的资产的功能和类型。 ERC-20 设定了可替代代币的标准,这意味着每个代币在类型和价值上都与另一个代币相同,类似于传统加密货币的运作方式。该标准对于创建可互换且统一的数字货币至关重要。 ERC-721引入了不可替代代币(NFT)的概念,它们彼此不同并代表独特的资产。该标准通常用于数字收藏品和艺术品,可以对具有特定特征的单个物品进行标记化。 ERC-1155 被称为多代币标准,提供多功能智能合约接口,能够在单个合约中处理多种代币类型。这种创新方法允许 ERC-1155 代币封装 ERC-20 和 ERC-721 标准的功能,支持可替代和不可替代代币。这种灵活性使得 ERC-1155 对于需要混合可替代和不可替代资产的应用程序特别有用,例如游戏或去中心化金融。这些标准共同增强了以太坊生态系统托管广泛数字资产的能力,从可互换的货币代币到独特的数字收藏品和混合应用程序,展示了该平台的适应性和区块链领域的巨大创新潜力。 ERC-20 代币的优点和缺点ERC-20代币的优点互操作性:ERC-20 代币的一个突出特点是它们能够在以太坊生态系统中无缝交互,从而实现不同代币之间的轻松交换。这种互操作性支持从交易到项目融资的各种应用程序。增强的安全性:ERC-20 代币建立在以太坊区块链之上,受益于其强大的安全措施。不变性和去中心化等功能可防止操纵,确保代币完整性。定制灵活性:开发人员可以自由定制 ERC-20 代币以满足项目特定要求,包括代币供应、小数精度和独特功能。透明交易:以太坊区块链的透明度允许跟踪 ERC-20 代币变动,提供清晰的交易历史并增强参与者之间的信任。市场流动性:ERC-20代币以其流动性而闻名,这使其对投资者和交易者具有吸引力。在交易所买卖这些代币的便捷性有助于其受欢迎。用户友好:通过 MyEtherWallet 和 MetaMask 等工具促进 ERC-20 代币的可访问性,促进区块链社区内的广泛使用和创新。 ERC-20代币的缺点功能有限:尽管稳定,但 ERC-20 代币的标准化性质可能会限制复杂智能合约或自动化流程所需的高级功能,从而给需要更大多功能性的项目带来挑战。安全漏洞:ERC-20代币在继承以太坊安全特性的同时,也存在一些漏洞,包括易受智能合约漏洞和网络拥塞等影响,从而导致潜在的安全风险。可变汽油费:涉及 ERC-20 代币的交易会产生汽油费,该费用可能会随着网络拥塞而大幅波动,影响成本可预测性,并可能给小投资者带来负担。交易所兼容性问题:并非所有加密货币交易所都支持 ERC-20 代币,这可能会限制其流动性和投资者的交易选择。对兼容交易所的研究对于获得最佳交易体验至关重要。治理和透明度问题:治理不善和缺乏透明度可能会导致代币倾销和内幕交易等问题,从而损害投资者的信心和代币的可信度。无可否认,ERC-20 代币标准塑造了以太坊区块链的格局,提供了促进创新和参与的一系列好处。然而,它带来的挑战,包括安全问题和某些应用程序的有限功能,凸显了生态系统内持续开发和治理改进的重要性。

请注意,Plisio 还为您提供:

单击 2 次即可创建加密发票 and 接受加密捐赠

12 整合

BigCommerce

Ecwid

Magento

Opencart

osCommerce

PrestaShop

VirtueMart

WHMCS

WooCommerce

X-Cart

Zen Cart

Easy Digital Downloads

6 最流行的编程语言库

PHP 图书馆

Python 图书馆

React 图书馆

Vue 图书馆

NodeJS 图书馆

Android sdk 图书馆

19 加密货币和 12 区块链

Bitcoin (BTC)

Ethereum (ETH)

Ethereum Classic (ETC)

Tron (TRX)

Litecoin (LTC)

Dash (DASH)

DogeCoin (DOGE)

Zcash (ZEC)

Bitcoin Cash (BCH)

Tether (USDT) ERC20 and TRX20 and BEP-20

Shiba INU (SHIB) ERC-20

BitTorrent (BTT) TRC-20

Binance Coin(BNB) BEP-20

Binance USD (BUSD) BEP-20

USD Coin (USDC) ERC-20

TrueUSD (TUSD) ERC-20

Monero (XMR)

分享到

最新的文章

CoinSpot 评论:2024 年的详细信息、费用和功能

Mar 15, 2024

Dex Screener:2024 年如何使用

Mar 14, 2024

2024 年葡萄牙加密货币税收指南

Mar 13, 2024

什么是 Chainlink(LINK)?

Mar 13, 2024

Bybit 评论:优点、缺点和特点

Mar 12, 2024

2024 年如何兑现加密货币和比特币

Mar 12, 2024

美国国税局 (IRS) 能否在 2024 年追踪加密货币?

Mar 11, 2024

最佳 DeFi 交易所

Mar 11, 2024

dYdX 评论:优点、缺点和功能

Mar 10, 2024

托管钱包与非托管加密钱包

Mar 10, 2024

Exodus 钱包评论:2024 年的优点、缺点和功能

Mar 8, 2024

Kraken 评论:2024 年的优点、缺点和功能

Mar 8, 2024

加拿大加密货币税收指南(2024 年 CRA 规则)

Mar 7, 2024

Polymarket:去中心化预测市场如何运作

Mar 6, 2024

2024 年最佳 DeFi 加密货币

Mar 6, 2024

体育用品进入加密世界。轻松接受付款。

Mar 6, 2024

MEV Bot:以太坊套利分步手册

Mar 6, 2024

什么是闪电贷?

Mar 5, 2024

最佳区块链游戏公司

Mar 5, 2024

2024 年最佳白标 NFT 市场

Mar 4, 2024

产品

商业

个人的

价钱

批量支付

白色标签

发票

捐款

集成

资源

应用程序接口

博客

安全

漏洞赏金

常问问题

联系我们

政策

隐私政策

服务条款

跟着我们

简体中文

English

اَلْعَرَبِيَّةُ

Deutsch

ελληνικά

Español

فارسی

Français

हिन्दी

Bahasa Indonesia

Italiano

日本語

한국어

Polski

Português

Русский

ไทย

Türkçe

Українська

Tiếng Việt

简体中文

© 2024 Plisio, 公司。保留所有权利。

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年3月13日(opens in a new tab)(opens in a new tab)(opens in a new tab)学习学习中心什么是以太坊?什么是以太币 (ETH)?以太坊钱包什么是 Web3?智能合约Gas fees运行节点以太坊安全和预防欺诈措施测试中心以太坊词汇表用法指南选择钱包获取以太币Dapps - 去中心化应用稳定币NFT - 非同质化代币DeFi - 去中心化金融DAO - 去中心化自治组织去中心化身份质押ETH二层网络构建构建者首页教程相关文档通过编码来学习设置本地环境资助基础主题用户体验/用户界面设计基础Enterprise - Mainnet EthereumEnterprise - Private Ethereum参与社区中心在线社区以太坊活动为 ethereum.org 做贡献翻译计划以太坊漏洞悬赏计划以太坊基金会以太坊基金会的博客(opens in a new tab)生态系统支持方案(opens in a new tab)Devcon(opens in a new tab)研究以太坊白皮书以太坊路线图安全性增强以太坊技术史开放研究以太坊改进提案 (Eip)以太坊治理关于我们以太坊品牌资产Code of conduct工作机会隐私政策使用条款缓存政策联系我们(opens in a new tab)本页面对你有帮

ERC20解读 | 登链社区 | 区块链技术社区

ERC20解读 | 登链社区 | 区块链技术社区

文章

问答

讲堂

专栏

集市

更多

提问

发表文章

活动

文档

招聘

发现

Toggle navigation

首页 (current)

文章

问答

讲堂

专栏

活动

招聘

文档

集市

搜索

登录/注册

ERC20解读

Confucian

更新于 2022-04-04 19:54

阅读 6961

对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 代币

3968 浏览

Michael.W基于Foundry精读Openzeppelin第39期——ERC20.sol

506 浏览

教程:如何在没有 Web 界面的情况下创建 ERC20桥

1574 浏览

一个简单的ERC20代币空投合约

2653 浏览

发布一款ERC20代币,并开发成Dapp

1548 浏览

Aptos合约开发之部署ERC20合约

3944 浏览

相关问题

请教下大家,Swap如何实现卖币手续费

2 回答

如何从发起部署的地址中,转移一部分代币到已经部署的合约地址中,麻烦那位大佬看一下

5 回答

空投的默克尔树如何防止生日攻击?

2 回答

bsc链上的erc20合约,要求只有一点买卖的时候2%兑换成bnb发送到营销钱包,现在的问题是添加流动性会一直报错Fail with error 'TransferHelper::transferFrom: transferFrom failed'

2 回答

eth中如何判断合约是erc20合约

2 回答

寻找使用Vyper部署的带有交易税的ERC20代币模版

1 回答

0 条评论

请先 登录 后评论

Confucian

关注

贡献值: 57

学分: 83

Keep Learning

文章目录

关于

关于我们

社区公约

学分规则

Github

伙伴们

DeCert

ChainTool

GCC

合作

广告投放

发布课程

联系我们

友情链接

关注社区

Discord

Twitter

Youtube

B 站

公众号

关注不错过动态

微信群

加入技术圈子

©2024 登链社区 版权所有 |

Powered By Tipask3.5|

粤公网安备 44049102496617号

粤ICP备17140514号

粤B2-20230927

增值电信业务经营许可证

×

发送私信

请将文档链接发给晓娜,我们会尽快安排上架,感谢您的推荐!

发给:

内容:

取消

发送

×

举报此文章

垃圾广告信息:

广告、推广、测试等内容

违规内容:

色情、暴力、血腥、敏感信息等内容

不友善内容:

人身攻击、挑衅辱骂、恶意行为

其他原因:

请补充说明

举报原因:

取消

举报

×

如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!

Buy/Sell Bitcoin, Ether and Altcoins | Cryptocurrency Exchange | Binance

Buy/Sell Bitcoin, Ether and Altcoins | Cryptocurrency Exchange | Binance

Error 403 Forbidden - This request is blocked.

For security reasons you can't connect to the server for this app or website at this time.

It maybe that you have too many requests or the illegal request payload is identified as an attack.

Please try again later.