什么是ERC-20? - 知乎切换模式写文章登录/注册什么是ERC-20?穆逸扬Myytydy用注意力写作,用比特币存钱摘要简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币;我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献,也是以太坊网络第一个真正意义上的杀手级应用。以下是正文这次的更新我们来聊聊ERC-20这个你很可能听过,但大概率一知半解的区块链“黑话”。如果你是定投人生课堂的成员,或者正在践行定投区块链数字资产的策略,相信ERC-20这个词对你而言一定不陌生。ERC-20的定义如同CoinDesk专栏作者 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中所说的:ERC-20以太坊代币标准是创建与更广泛的以太坊网络兼容的可替换代币的蓝图。以太坊,或称Ethereum,是一种加密货币,允许创建各种应用,包括代币,与大多数传统应用不同,它不需要中心化服务机构就可以运作。上面引述的内容可能不太好理解,简单来说,ERC-20就是一套基于以太坊网络的标准代币发行协议。其中的ERC是"EthereumRequest for Comment"也就是“以太坊征求意见协议”的缩写。和其他的开源社区一样,以太坊会使用这样的方式收集开发者的反馈、并在批准后作为后续开发的执行标准。ERC-20的价值和影响毫无疑问,ERC-20是所有ERC协议中最广为人知的一个。我们甚至可以将ERC-20视为以太坊网络为早期区块链世界做出的最重要贡献(此处完全可以去掉“之一”,我甚至不介意再去掉“早期”)。是的,在我看来ERC-20就是以太坊网络第一个真正意义上的杀手级应用。正是因为有了ERC-20,开发者们得以高效、可靠、低成本地创造专属自己项目的代币。也正是这一协议提供的这种极大的便利,使得首次代币发行,也就是大名鼎鼎同时饱受争议的ICO,能一度在区块链世界大行其道——助长大量骗局的同时,也在客观上推动了区块链相关技术与应用的爆发式增长。更有趣的是,ERC-20的火爆甚至直接催生了一些类似TRC-20这样,连协议的数字代号都懒得改一下的像素级山寨竞品。一个便于理解的类比如果上面的这些叙述还是让你一知半解,甚至完全摸不到头脑,我们不妨打个容易理解的比方:如果我们把众多区块链项目的开发者,看作是在一个小区门口商铺里,经营不同业态的众多商户。这些商户根据自己的专长提供各自不同的商品和服务,也都希望发行自己店铺专属的消费储值卡。方便消费者光顾的同时,也能提升用户的体验和粘性。以太坊就像是运营这个小区底商的物业公司,它提供一整套标准化的储值卡发放协议和配套服务。借助这套叫做ERC-20的整体解决方案,每个商户(开发者)都可以傻瓜式地发行专属于自己店铺的消费储值卡,同时由于这种储值卡采用了统一的协议,可以非常方便地和其他商户的储值卡做无缝兑换。于是借助ERC-20,用户可以通过持有其中一种储值卡(token)很方便地享受整个生态的各种服务;商户(开发者)则节约了开发运营成本、同时提升了获取用户的效率;而物业公司(以太坊基金会和矿工)则可以通过做大生态体量实现更多的租金(ETH增值)和储值卡结算手续费(Gas费用)收入。ERC-20就是用这种做大生态价值的方式,实现了用户、开发者和以太坊网络三方面的共赢。ERC-20的应用案例为了让你对ERC-20有更具象化的认识,这里援引 Alyssa Hertig 在 What is the ERC-20 Ethereum Token Standard? 中列举的一些比较知名的基于ERC-20协议代币:Tether (USDT)Chainlink (LINK)Binance coin (BNB)USD coin (USDC)Wrapped bitcoin (WBTC)Dai (DAI)需要特别指出的是,这上面提到的Tether发行的稳定币USDT除了基于ERC-20协议的版本之外,其实还有基于其他公链发行的多个版本,只不过ERC-20版的发行量最大,知名度也最高。ERC-20与BOX的关系ERC-20版本的USDT,在我们定投人生课堂的战友定投BOX的过程中,也有很广泛的应用。比如通过ExinOne(Mixin ID:7000101276),可以轻松实现存USDT自动执行每周/每日定投BOX的操作。说到BOX这个区块链数字资产开源配方,它和ERC-20的关系也十分密切——其中的两个成分,XIN、UNI就是基于ERC-20协议发行的代币,此外BOX本身同样是一个基于此协议发行的Token——可以说,如果没有ERC-20,BOX这个区块链数字资产开源配方就不会是现在这个样子了。参考内容What is the ERC-20 Ethereum Token Standard?ERC 协议终极解读:ERC-20你常听到的 ERC20 和 ERC721 到底是什么?一文弄懂什么是 ERC20BOX简介发布于 2021-12-02 16:01虚拟货币区块链(Blockchain)ethereum赞同 5添加评论分享喜欢收藏申请
USDT充币提币ERC20、TRC20、Omni如何选择?有啥区别? - 知乎切换模式写文章登录/注册USDT充币提币ERC20、TRC20、Omni如何选择?有啥区别?usdt区块链是现在,区块链是未来。在充提USDT的时候,投资者发现有3个不同的链类型供选择,分别是ERC20、TRC20和Omni,而大多数投资者就卡在这里了,在三者之间不知道该如何选择,甚至都不了解这三者是什么,简单点说ERC20是以太坊区块链的链类型,TRC20是波场区块链的链类型,而Omni是比特币区块链网络的链类型。USDT充币提币ERC20、TRC20、Omni如何选择?除了地址不同之外,选择不同的链类型,转转账的速度和手续费也是不一样的。如果你希望可以快速转账,追求的是速度,那就应该选择波场区块链的TRC20链类型。波场网络TPS达到1500TPS,目前来说转账最快到账的是波场USDT。如果你在意的是手续费,希望转账手续费能低一些,那也应该选择TRC20链类型。因为TRC20链类型转账,手续费为0。而ERC20链类型的手续费是2USDT,大概是14块钱。OMIN链类型手续费最贵,需要5个USDT,大概是35人民币。但是如果你希望转账能安全一点,那就选择比特币网络的OMIN链类型,这个链类型虽然手续费高了一点,但是安全性好。贵,也是有道理的嘛。USDT充币提币ERC20、TRC20、Omni有啥区别?1、Omni-USDT的安全性最好,但转账速度太慢。要是你有不着急交易的大额订单,可以优先选择Omni-USDT。2014年,USDT于比特币网络上诞生,于2015年2月正式上线几大主流交易所。在2018年之前,USDT的转账路径只有一条,那就是基于比特币网络的Omni-USDT。Omni-USDT存储在比特币地址上,因此每次转账的时候,需要支付比特币作为矿工手续费。Omni-USDT于比特币网络的链上,黑客攻击的成本很高,所以资产相对安全性较高。但是其交易速度非常慢,已经无法满足当今加密交易市场的需求,但很多大宗交易还是会倾向于Omni-USDT。2、ERC20-USDT的安全性和转账速度居中。适用于数字货币市场的频繁交易。要是你经常做短线交易,可以优先选择ERC20-USDT。2018年,以太坊网络开始流行,在区块链应用也大面积展开,ERC20-USDT出现。和Omni-USDT一样,使用ERC20-USDT同样需要支付旷工费,但转账速度有了显著的提升。由于安全性好、转账速度快,ERC20-USDT被市场广泛接受,USDT的发行者泰达公司也开始支持更高效的以太坊ERC20。由于综合指数比较高,在主流交易平台比较受欢迎。3、TRC20-USDT的转账速度最快,而且链上转账无需手续费,但安全性比较低。适合需要快速到账的朋友,建议小额为主,现在一次转账一般都只需要几分钟时间。2019年,泰达公司宣布在波场上发行了基于TRC-20协议的USDT,TRC20-USDT诞生。发行时承诺完全公开透明,零转账费,秒级到账。和前两者不同的是,目前TRC20-USDT转账是不收取手续费的。ERC20、TRC20、Omni这三种类型的USDT在交易所内并没有差别,但在链上是不互通的,也就是说Omni上的USDT是无法转到另外两条链上的,所以在交易所充提USDT时一定要留意地址种类。发布于 2021-03-15 14:34比特币 (Bitcoin)USDT比特币合约赞同 13630 条评论分享喜欢收藏申请
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 条评论分享喜欢收藏申请
3分钟了解TRC20、ERC20到底差在哪? - 知乎切换模式写文章登录/注册3分钟了解TRC20、ERC20到底差在哪?托尼金铲铲赏金赛,招高玩选手➡️znifc9999我们在转帐时,常常需要选择主网类型(提领地址的协议),会出现TRC-20、ERC-20、Omni 等等,不同的选项有不同的手续费,那这些英文代表什么意思呢?我们到底要怎么选?相信看完这篇你一定搞懂TRC20 ERC20 差别! ! !代币协议标准一般的加密货币都有自己依附的区块链,例如以太币就是建立在以太坊这个区块链上面、比特币建立在比特币区块链上而想要在这些区块链上面发行货币,就必须遵守各区块链的规则例如想在以太链上发行加密货币,就必须遵守以太链上的「ERC-20协议」,ERC全名是” Ethereum Request for Comment ” ,这个协议中包含了发行货币的标准和注意事项那我们平常转帐最常转的应该是USDT,USDT 不只发行在一个区块链上,Tether公司发行USDT在比特币链、以太坊、Tron链…等区块链上,那发行在不同区块链上就要遵守不同区块链的协议在转帐时常看到的Omni、ERC-20、TRC-20分别是比特币区块链、以太坊、TRON区块链上的协议下面会介绍三种链上转帐的差异!OmniOmni 是比特币区块链上的协议2014年,Tether公司基于比特币区块链「Omni协议」发行USDT,转帐需要支付一些BTC做为手续费转帐速度虽然慢,但是因为是基于比特币区块链,所以安全性相较其他两者高,所以如果是大笔金额的转帐通常会用Omni转帐手续费:通常>10 USD (各交易所不一样)最小转帐数量:最高到帐时间:慢,十几分钟到几天安全性:最安全转帐帐号地址开头:1、3ERC-20ERC-20 是以太坊上的协议2018年以太坊开始热门,所以Tether公司在以太坊上面发行USDT,转帐速度大幅上升转帐手续费(以币安为例):10 USDT (各交易所不一样)最小转帐数量(以币安为例):50 USDT (各交易所不一样)到帐时间:普通、易堵塞,几分钟到几十分钟安全性:普通转帐帐号地址开头:0xTRC-20TRC-20 是波场(TRON)区块链上的协议因为以太坊过于壅塞,转帐手续费越来越高,所以在2019年4月泰达公司(Tether)在TRON 上发行USDT,TRC-20上的USDT特色就是转帐速度快、手续费相当低! ! ! 目前被广泛使用~转帐手续费(以币安为例):1 USDT (各交易所不一样,MAX交易所不用手续费)最小转帐数量(以币安为例):10 USDT (各交易所不一样)到帐时间:快,几秒钟安全性:相较其他两者低转帐帐号地址开头:Tx因为TRC-20的手续费相当便宜且快速,所以大部分可能会选择TRC-20比较多,如果是加密货币新手可以选择TRC-20来转USDT~结论所以平常看到的TRC-20、ERC-20、Omni,其实就是Tether公司在不同区块链上发行的USDT,可以想成用不同管道转帐比较好理解,手续费、速度等等会有所不同例如把用Omni转帐想成去银行临柜办理,要排队排比较久;用TRC-20转帐想成用网络银行转帐,速度相当快,有时手续费还不用钱~要注意不同区块链上的资产是不能互相转帐的!所以在转帐的时候一定要选择正确的链、协议,转帐前要注意地址是否正确希望看完这篇文章,有帮助你了解TRC20 ERC20 差别!发布于 2023-06-28 16:36・IP 属地江西$BTC赞同 1添加评论分享喜欢收藏申请
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.
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: 59010
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应用代币分析白噪音Ƀlockchain Đata Ξxpl0it量子链(QTUM)量子链致力于开发比特币和以太坊之外的第三种区块链生态系统,通过价值传输协议(“Value Transfer Protocol”)来实现点对点的价值转移,并根据此协议,构建一个支持多个行业(包括金融、物联网、供应链、社交、游戏等)的去中心化的应用开发平台(DApp Platform)https://www.zhihu.com/video/881665750945923072EOS EOS是一种全新的区块链架构,旨在实现分布式应用的性能拓展。EOS 项目的目标是实现一个类似操作系统一样的支撑应用程序的区块链架构。该架构可以提供账户,身份认证,数据库,异步通信以及可在数以百计的 CPU 或群集上的程序调度。该技术的最终形式是一个区块链体系架构,该区块链每秒可以支持数百万个交易,同时普通用户无需支付使用费用。https://www.zhihu.com/video/881669030837104640TENX(PAY)TenX电子钱包能够实现让用户通过智能手机或信用卡消费他们的区块链资产,TenX钱包支持多币种,用户和企业能够以去中心的方式无缝地交易其区块链资产,消除与当前中心化解决方案相关的任何风险。在现实支付中,用户可以在 TenX 应用上自由选择不同的区块链资产作为支付来源,通过 TenX 电子钱包,极为便利地实现大范围的区块链资产转换支付,如 BTC、ETH 和 DASH 等。在实际交易发生之前,加密货币不需要转换为法定货币,这种转换将会在交易中实时进行。https://www.zhihu.com/video/881666014083940352OmiseGo(OMG) OmiseGo 是基于以太坊的新型金融平台,是处理支付处理器、网关和金融机构之间基本协调问题的区块链网络,通过实现大量的、低成本的去中心化交易,提供跨越不同货币和资产类型和公司分类账的新一代资产转移服务。OmiseGo的目标客户群是东南亚国家的人口,无论其是否正在使用正规金融服务。通过OmiseGo网络,为每个人提供可替代的金融和数字商业工具,无需再通过传统的银行,机构和卡片网络,这些终端用户将能够在低成本的条件下灵活完成支付、汇款、薪水存储、B2B 商业、供应链融资、信用制度、资产管理和贸易以及各种随需应变的金融服务。https://www.zhihu.com/video/881666152466632704Augur(REP)Augur 是建立在以太坊平台上的去中心化预测市场平台。利用 Augur ,任何人都可以为任何自己感兴趣的主题(比如美国大选谁会获胜)创建一个预测市场,并提供初始流动性,这是一个去中心化的过程。作为回报,该市场的创建者将从市场中获得一半的交易费用。普通用户可以根据自己的信息和判断在 Augur 上预测、买卖事件的股票,例如美国总统大选。当事件发生以后,如果你预测正确、持有正确结果的股票,每股你将获得1美元,从而你的收益是1美元减去当初的买入成本。如果你预测错误、持有错误结果的股票,你将不会获得奖励,从而你的亏损就是当初的买入成本。https://www.zhihu.com/video/881666219839750144GOLEM(GNT)Golem 是建立在以太坊平台上的去中心化计算机算力租赁平台。通过 Golem 平台,任何用户都可以成为算力的发售方和租用者。无论用户提供的是一台闲置的家用电脑还是几台大型的数据中心,都可以加入到 Golem 平台中。基于以太坊的交易系统被应用于 Golem 平台,用于结算算力提供者的收益和算力使用者所需要支付的费用。https://www.zhihu.com/video/881666279306579968STATUS(SNT)SNT 是一款开源通讯平台 Status ——用于与运行在以太坊网络上的去中心化应用进行交互的移动应用的网络代币。SNT 作为用来为 Status 网络提供支持的模块化实用代币,包括去中心化的推送式通知市场,Status 客户端的管理,社区内容的归纳整理,以及如 Tribute to Talk 等的社交通讯工具。Status 还提出了法币兑换加密货币的“柜员网络”,去中心化应用程序目录,贴纸市场,并展示了在用户获取引擎方面的研究,从而得以扩大网络。https://www.zhihu.com/video/881668957214507008FirstBlood(1ST)第一滴血,是一个可以让玩家随时随地挑战对手并获得赏金的去中心化电竞平台。全球电竞市场正在迅猛增长,而电子竞技平台所提供的公平性与安全性却参差不齐。当前电子竞技平台面临的首要问题是没法提供一个可以信赖的仲裁机制并且没有自动化的赏金分发系统。第一滴血项目,是搭建于以太坊上的区块链平台。该平台致力于使用去中心化的方式解决中心平台的信任问题,并利用智能合约解决赏金支付问题。https://www.zhihu.com/video/881669174152294400Bancor(BNT)班科协议使得智能合约区块链上代币们的价格发现和流动机制成为可能。这些“智能代币”持有一种或多种其它代币作为准备金。这些被持有的代币,我们统称为“准备金代币”。持有这些“智能代币”的人,可以即时的买入或卖出这些“智能代币”以交换它持有的某种“准备金代币”。这些即时的买入或卖出过程是通过“智能合约”实现的。交易价格是通过一个以与交易量为变量的数学公式计算得出的。https://www.zhihu.com/video/881666685411659776BasicAttentionToken(BAT)基本注意力代币是数字广告行业的全新货币,使用此代币可以支付内容商的内容费和用户的注意力,同时让广告商得到很理想的投资回报。https://www.zhihu.com/video/881666735030276096以太坊与ICO基础数据根据Etherscan数据显示:截至8月17日,以太坊拥有余额账号总量达到450万个,智能合约地址136万个;ERC20代币种类5300个,其中市值在1000万美元以上的43个;持有主流ICO代币的账号数量约30万个,占全体ETH有效账号的6.7%以太坊主网络交易次数在2000次以上且持有ERC20代币的ETH账户只有60个,以交易所冷钱包为主,包括Parity多重签名钱包漏洞的白帽地址。66%的以太坊账号交易次数在10次以内,账户数与交易频次呈显著的幂律分布OMG与量子链市值超过8亿美元PAY与EOS市值约5亿美元ICN、REP、BAT、GNT、CVC、GNO、SNT市值在2亿~3亿之间BNT、STORJ、FUN、DNT、1ST代币总市值约为1亿美元ERC20代币基础数据EOS与GNT拥有最多的账户,分别超过5万个REP与SNT数量在2万~3万之间PAY、STORJ、BNT、OMG、CVC、量子链、ICN与BAT账户数约为1万量子链与OMG账号平均持有该代币的价值较高,约7万美元GNO单账号价值约4.5万美元1ST、FUN、PAY、BAT、ICN单账号价值在2万~3万之间造成此局面的原因有:①项目本身质量好,人均持有量较高 ②升值幅度较大 ③交易所账户等大户持有量较高,筹码较为集中1ST、OMG、GNO、BAT、ICN等币种换手率较高,平均单账户交易次数超过6次GNT、PAY、SNT、EOS、QTUM、CVC平均交易次数在4~6次之间DNT、BNT、STORJ、FUN、REP的换手率较低,尚未得到市场有效炒作从合约内总交易次数上看,GNT与EOS占据第一阵营,交易次数均超过25万次;SNT、PAY、OMG、ICN、BAT、QTUM紧随其后,交易次数超过5万次;其余币种交易总次数显著较低结论:ICO仍处于市场发展初期,投资者人数仅为数十万量级大部分成功ICO的代币持有账户数量并不多,基本都在1万以内项目价值与持有代币账户数并无必然关系,OMG与量子链用户回报显著较高有落地场景的币种如OMG与PAY,得到市场认可也较高BNT、EOS、CVC、SNT等币种的升幅较小,未来有较大的运作空间更多ICO数据分析请关注微信公众号:区块链大数据分析编辑于 2017-08-30 00:21区块链(Blockchain)比特币 (Bitcoin)赞同 165 条评论分享喜欢收藏申请转载文章被以下专栏收录区块链大数据分析基于EOS/ETH区块链的交易数
创建并部署ERC20代币 | 登链社区 | 区块链技术社区
文章
问答
讲堂
专栏
集市
更多
提问
发表文章
活动
文档
招聘
发现
Toggle navigation
首页 (current)
文章
问答
讲堂
专栏
活动
招聘
文档
集市
搜索
登录/注册
创建并部署ERC20代币
aisiji
更新于 2022-03-11 15:22
阅读 7613
本文通过创建一个代币深入讲解ERC20
> 本文通过创建一个代币深入讲解ERC20
![1_FhxeUTY3vrk3oECG3-hC2w](https://img.learnblockchain.cn/2022/03/02/1_FhxeUTY3vrk3oECG3-hC2w.png!/scale/70)
图片来源: Undraw.co
## ERC20代币标准
第一个标准由Fabian Vogelsteller于2015年11月以ethereum request for Comments(ERC)引入,它被自动分配到GitHub第20个议题,所以叫“ERC20代币”。目前绝大多数代币都基于ERC20标准。ERC20后来变成了以太坊改进提案20(EIP-20),但是大部分仍然使用它最初的名字,ERC20。
ERC20是一个同质化代币标准,意思是不同的ERC20代币是可互换的并且不具有独特属性。
[ERC20标准](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md)为实现代币的合约定义了一个通用接口,这样任何兼容的代币都可以用同样的方式访问和使用。这个接口由许多必须在每次实现中都出现的函数构成,以及一些开发者可能添加的可选函数和属性。
## ERC20需要的函数和事件
一个ERC20的代币合约必须至少提供下面这些函数和事件:
`totalSupply`: 返回当前代币总量,可以是一个固定值或者变量。
`balanceOf`:返回给定地址的代币余额
`transfer`: 从执行转账的地址余额中将指定数量的代币转移到指定地址。
`transferFrom`: 从一个账户到另一个账户,指定发送者,接收者和转移的代币数量。与`approve`结合使用。
`approve`: 指定一个被委托地址和委托代币数量,被委托地址可以在不超过委托数量的前提下多次从委托账户转移代币。
`allowance`: 给定一个所有者地址和一个被委托地址,返回被委托代币余额。
Transfer: 在成功转移(调用`transfer`或者`transferFrom`)后触发的事件(即使转移数量为0)。
Approval: 成功调用`approve`的事件日志。
## ERC20 可选函数
`name`: 返回代币的可读名称(如“US Dollars”)。
`symbol`: 返回代币的可读符号(如“USD”)。
`decimals`: 返回代币数量的小数点位数。例如,如果`decimals`为2,表示小数点后2位。
ERC20 接口是用 Solidity 定义的。
下面是Solidity 的 ERC20接口规范:
```
contract ERC20 {
function totalSupply() constant returns (uint theTotalSupply);
function balanceOf(address _owner) constant returns (uint balance);
function transfer(address _to, uint _value) returns (bool success);
function transferFrom(address _from, address _to, uint _value) returns
(bool success);
function approve(address _spender, uint _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns
(uint remaining);
event Transfer(address indexed _from, address indexed _to, uint _value);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
```
## ERC20 数据结构
如果你检查任何一个ERC20实现,你会发现它包含两个数据结构,一个用来跟踪余额(balance),另一个用来跟踪委托代币余额(allowance)。在Solidity中,都是用数据映射实现的。
第一个数据映射允许代币合约跟踪谁拥有代币。每次交易都是从一个余额扣除同时在另一个余额增加:
```
mapping(address => uint256) balances;
```
第二个数据结构是委托代币余额(allowance)的数据映射。正如我们将在下一节看到的,ERC20代币所有者可以让一个被委托者花费自己余额中一定数量的代币(allowance) 。
ERC20 合约用一个二维映射跟踪委托代币余额,其主键是代币所有者的地址,映射到被委托地址和对应的委托代币余额:
```
mapping (address => mapping (address => uint256)) public allowed;
```
## ERC20工作流程:“transfer” 和 “approve + transferFrom”
ERC20代币标准有两个交易函数。你可能想知道为什么。
ERC20允许两种不同的工作流程。第一种是一笔交易,使用`transfer`函数的的简单流程。这个流程用于一个钱包发送代币到另一个钱包。
执行转账合约非常简单。如果Alice想要发送10个代币给Bob,她的钱包会发送一笔交易到代币合约的地址,调用`transfer`函数,并且参数为Bob的地址和10。代币合约修改Alice的余额(-10)和Bob的余额(+10),然后发出一个`Transfer`事件。
第二种流程是两笔交易,`approve`+`transferFrom`。这个流程允许代币所有者将控制权委托给另一个地址。通常用于将控制权委托给一个分配代币的合约,也可以被交易所使用。
例如,如果一个公司正在为ICO发售代币,他们可以委托一个众筹合约地址来分发一定数量的代币。这个众筹合约可以通过`transferFrom`将代币合约所有者的余额转给每一个代币买家,如下图所示。
> 注意:首次代币发行(ICO)是公司或者组织为了筹集资金而出售代币的众筹机制。这个术语源自首次公开募股(IPO),这是上市公司在证券交易所向投资者出售股票的过程。与高度监管的IPO市场不同,ICO是开放的、全球化的、混乱的。本文对ICO的示例和解释并非对此类筹款活动的认可。
![1_eLTjPYZzUpalJTbsVDyZZw](https://img.learnblockchain.cn/2022/03/02/1_eLTjPYZzUpalJTbsVDyZZw.png!/scale/60)ERC20 workflow
## ERC20实现
虽然大约30行Solidity代码就可以实现一个ERC20代币,但大部分的实现都是更复杂的。这是为了解决潜在的漏洞。EIP-20标准提到两种实现:
[Consensys EIP20](https://github.com/ConsenSys/Tokens/blob/master/contracts/eip20/EIP20.sol) —— 一种简单且易读的ERC20代币的实现。
[OpenZeppelin StandardToken](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v1.12.0/contracts/token/ERC20/StandardToken.sol) —— 这个实现兼容ERC20,并且有额外安全措施。它形成了OpenZeppelin库的基础,可以实现更复杂ERC20代币,如筹款上限,拍卖,期权等功能。
## 发起自己的ERC20代币
接下来我们创建并发起自己的代币。下面的例子,将使用Truffle框架。假设你已经安装了Truffle,如果没有安装,请用npm安装:
```
npm i truffle
```
假设我们的代币叫“Mastering Ethereum Token”,我们用符号“MET”代表它。
> 注意:你可以在[这里](https://github.com/ac12644/METoken.git)找到这个例子。
首先,我们创建并初始化一个Truffle项目目录。运行下面4个命令并接受所有默认答案:
```
$ mkdir METoken
$ cd METoken
METoken $ truffle init
METoken $ npm init
```
你现在应该有下面的目录结构了:
```
METoken/
+---- contracts
| `---- Migrations.sol
+---- migrations
| `---- 1_initial_migration.js
+---- package.json
+---- test
`---- truffle-config.js
```
编辑`truffle-config.js`配置文件,配置Truffle环境,或者复制下面的示例:
```
// Install dependencies:
// npm init
// npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
// Create .env in project root, with keys:
// ROPSTEN_PRIVATE_KEY="123abc"
// MAINNET_PRIVATE_KEY="123abc"
require('dotenv').config();
const Web3 = require("web3");
const web3 = new Web3();
const WalletProvider = require("truffle-wallet-provider");
const Wallet = require('ethereumjs-wallet');
var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
module.exports = {
networks: {
dev: { // Whatever network our local node connects to
network_id: "*", // Match any network id
host: "localhost",
port: 8545,
},
mainnet: { // Provided by Infura, load keys in .env file
network_id: "1",
provider: mainNetProvider,
gas: 4600000,
gasPrice: web3.utils.toWei("20", "gwei"),
},
ropsten: { // Provided by Infura, load keys in .env file
network_id: "3",
provider: ropstenProvider,
gas: 4600000,
gasPrice: web3.utils.toWei("20", "gwei"),
},
kovan: {
network_id: 42,
host: "localhost", // parity --chain=kovan
port: 8545,
gas: 5000000
},
ganache: { // Ganache local test RPC blockchain
network_id: "5777",
host: "localhost",
port: 7545,
gas: 6721975,
}
}
};
```
-truffle-config.js-
如果你用示例`truffle-config.js`,记住在包含你的测试私钥的`METoken`文件夹中创建一个`.env`文件,以便在以太坊公共测试网(如Ropsten or Kovan)上部署和测试。你可以从 MetaMask 导出测试网私钥。
这时,你的目录应该是这样的:
```
METoken/
+---- contracts
| `---- Migrations.sol
+---- migrations
| `---- 1_initial_migration.js
+---- package.json
+---- test
+---- truffle-config.js
`---- .env *new file*
```
### 警告
只能使用没有在以太坊主网上持有资产的测试密钥或者测试助记词。切勿将真正持有资产的密钥用于测试。
在我们的示例中,我们将导入 OpenZeppelin 库,这个库实现了一些重要的安全检查并且容易扩展:
```
$ npm install openzeppelin-solidity@1.12.0
+ openzeppelin-solidity@1.12.0
added 1 package from 1 contributor and audited 2381 packages in 4.074s
```
`openzeppelin-solidity`包会在`node_modules`目录下添加大约250个文件。OpenZeppelin库并不仅仅包含ERC20代币,我们只会使用其中一小部分。
接下来,开始写代币合约。创建一个新文件,`METoken.sol`,并从下面复制[示例](https://github.com/ac12644/METoken/blob/main/contracts/METoken.sol)代码。
```
pragma solidity ^0.4.21;
import 'openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol';
contract METoken is StandardToken {
string public constant name = 'Mastering Ethereum Token';
string public constant symbol = 'MET';
uint8 public constant decimals = 2;
uint constant _initial_supply = 2100000000;
function METoken() public {
totalSupply_ = _initial_supply;
balances[msg.sender] = _initial_supply;
emit Transfer(address(0), msg.sender, _initial_supply);
}
}
```
-METoken.sol-
`METoken.sol`合约——实现ERC20代币的Solidity合约,非常简单,因为它从OpenZeppelin库继承了所有功能。
示例 1. `METoken.sol`: 实现ERC20代币的Solidity合约
这里,我们定义了可选变量名,符号,和小数位数,也定义了一个`_initial_supply`变量——设为2100万个代币,代币数量可以细分到小数点后2位,也就是总共21亿份。在合约的初始化函数(构造函数)中我们设置`totalSupply`等于`_initial_supply`,并且将所有`_initial_supply`全部分配给创建`METoken`合约的账户(`msg.sender`)的余额。
现在我们用truffle来编译METoken代码:
```
$ truffle compile
Compiling ./contracts/METoken.sol...
Compiling ./contracts/Migrations.sol...
Compiling openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol...
```
如你所见,truffle 编译了 OpenZeppelin 库的必要依赖。
接下来我们编写一个迁移脚本来部署`METoken`合约。在`METoken/migrations` 文件夹中创建一个新文件`2_deploy_contracts.js`。复制下面[示例](https://github.com/ac12644/METoken/blob/main/migrations/2_deploy_contracts.js)代码:
```
var METoken = artifacts.require("METoken");
module.exports = function(deployer) {
// Deploy the METoken contract as our only task
deployer.deploy(METoken);
};
```
-2_deploy_contracts.js-
在部署到以太坊测试网之前,我们先启动一个本地区块链来测试。可以从命令行`ganache-cli` 或者图形用户界面来启动[ganache](https://learnblockchain.cn/article/3501)区块链。
ganache 启动,我们就可以部署 METoken 合约并且看到是否一切正常:
```
$ truffle migrate --network ganache
Using network 'ganache'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0xb2e90a056dc6ad8e654683921fc613c796a03b89df6760ec1db1084ea4a084eb
Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0
Saving successful migration to network...
... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying METoken...
... 0xbe9290d59678b412e60ed6aefedb17364f4ad2977cfb2076b9b8ad415c5dc9f0
METoken: 0x345ca3e014aaf5dca488057592ee47305d9b3e10
Saving successful migration to network...
... 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0
Saving artifacts...
```
在 ganache 控制台,我们可以看到已经创建了四笔新的交易:
![1_HMf2Ba_xvS8Oj1fkQ1wp3g](https://img.learnblockchain.cn/2022/03/02/1_HMf2Ba_xvS8Oj1fkQ1wp3g.png!/scale/50)
-ganache-
### 用 Truffle 控制台与 METoken 交互
我们可以通过 truffle 控制台在 ganache 区块链上与合约交互。这是一个交互式 JavaScript 环境,提供了对 truffle 环境的访问,并通过 web3 访问区块链。下面,我们将 truffle 控制台与 ganache 区块链连接:
```
$ truffle console --network ganache
truffle(ganache)>
```
`truffle(ganache)>`表明我们已经连接到 ganache 区块链,并且已经准备好输入命令。truffle 控制台支持所有 truffle 命令,所以我们可以从控制台编译和迁移。
我们已经运行了命令,所以让我们直接进入到合约本身。`METoken`合约在 truffle 环境中就像一个 JavaScript 对象。在提示符的地方输入METoken,就会清除整个合约定义:
```
truffle(ganache)> METoken
{ [Function: TruffleContract]
_static_methods:
[...]
currentProvider:
HttpProvider {
host: 'http://localhost:7545',
timeout: 0,
user: undefined,
password: undefined,
headers: undefined,
send: [Function],
sendAsync: [Function],
_alreadyWrapped: true },
network_id: '5777' }
```
`METoken`对象也揭露了几个属性,如合约地址(因为是用 migrate 命令部署的):
```
truffle(ganache)> METoken.address
'0x345ca3e014aaf5dca488057592ee47305d9b3e10'
```
如果我们想要与部署的合约交互,我们必须使用异步调用,以JavaScript “promise” 的形式。用 deployed 函数来获取合约实例,然后调用`totalSupply`函数:
```
truffle(ganache)> METoken.deployed().then(instance => instance.totalSupply())
BigNumber { s: 1, e: 9, c: [ 2100000000 ] }
```
接下来,让我们用 ganache 创建的账户来检查 METoken 余额,并且发送一些 METoken 到另一个地址。首先,获取账户地址:
```
truffle(ganache)> let accounts
undefined
truffle(ganache)> web3.eth.getAccounts((err,res) => { accounts = res })
undefined
truffle(ganache)> accounts[0]
'0x627306090abab3a6e1400e9345bc60c78a8bef57'
```
账户列表包含 ganache 创建的所有账户,`accounts[0]`是部署`METoken`合约的账户。它应该有`METoken`余额的,因为我们的`METoken`构造函数将所有token给到了这个地址。我们检查一下:
```
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(accounts[0]).then(console.log) })
undefined
truffle(ganache)> BigNumber { s: 1, e: 9, c: [ 2100000000 ] }
```
最后,通过调用合约的`transfer`函数从`accounts[0]`转移 1000.00 个 METoken 到`accounts[1]`:
```
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.transfer(accounts[1], 100000) })
undefined
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(accounts[0]).then(console.log) })
undefined
truffle(ganache)> BigNumber { s: 1, e: 9, c: [ 2099900000 ] }
undefined
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(accounts[1]).then(console.log) })
undefined
truffle(ganache)> BigNumber { s: 1, e: 5, c: [ 100000 ] }
```
> 提示:METoken可以精确到小数点后2位,意思是1个METoken在合约中其实是100份。当我们转移1000个METoken时,我们在调用`transfer`函数时指定的值是100000
如你所见,在会话中,`accounts[0]`现在有20,999,000 个MET,`accounts[1]`有1000个MET。
![1_z7tDVitXZ_XTytKu3bBU8Q](https://img.learnblockchain.cn/2022/03/02/1_z7tDVitXZ_XTytKu3bBU8Q.png!/scale/50)
-ganache-
## 向合约地址发送ERC20代币
到目前为止,我们已经创建了一个ERC20代币并从一个账户发送了一些代币到另一个账户。前面我们用来演示的账户都是[外部账户(external owned accouts)](https://learnblockchain.cn/article/320),意思是由[私钥](https://learnblockchain.cn/article/3624)控制的账户,不是一个合约。如果我们发送 MET 到一个合约地址又会发生什么呢?
首先,我们在测试环境部署另一个合约。这个例子,我们将直接用水龙头合约`Faucet.sol`。将它复制到`contracts` 目录下,这样就把它添加到 METoken 项目下。现在目录是这样的:
```
METoken/
+---- contracts
| +---- Faucet.sol
| +---- METoken.sol
| `---- Migrations.sol
```
**还要再添加一个迁移,将**`Faucet`**和**`METoken`**分开部署:**
```
var Faucet = artifacts.require("Faucet");
module.exports = function(deployer) {
// Deploy the Faucet contract as our only task
deployer.deploy(Faucet);
};
```
**在 truffle 控制台编译并迁移合约:**
```
$ truffle console --network ganache
truffle(ganache)> compile
Compiling ./contracts/Faucet.sol...
Writing artifacts to ./build/contracts
truffle(ganache)> migrate
Using network 'ganache'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x89f6a7bd2a596829c60a483ec99665c7af71e68c77a417fab503c394fcd7a0c9
Migrations: 0xa1ccce36fb823810e729dce293b75f40fb6ea9c9
Saving artifacts...
Running migration: 2_deploy_contracts.js
Replacing METoken...
... 0x28d0da26f48765f67e133e99dd275fac6a25fdfec6594060fd1a0e09a99b44ba
METoken: 0x7d6bf9d5914d37bcba9d46df7107e71c59f3791f
Saving artifacts...
Running migration: 3_deploy_faucet.js
Deploying Faucet...
... 0x6fbf283bcc97d7c52d92fd91f6ac02d565f5fded483a6a0f824f66edc6fa90c3
Faucet: 0xb18a42e9468f7f1342fa3c329ec339f254bc7524
Saving artifacts...
```
赞,现在我们向 Faucet 合约发送 MET :
```
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.transfer(Faucet.address, 100000) })
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(Faucet.address).then(console.log)})
truffle(ganache)> BigNumber { s: 1, e: 5, c: [ 100000 ] }
```
我们已经将 1000MET 转给了 Faucet 合约。现在,我们要如何取出这些代币呢?
记住,`Faucet.sol`是一个非常简单的合约。它只有一个用来提取以太币的函数`withdraw`,没有用来提取 MET 的函数,或者任何其他 ERC20 代币。如果我们用`withdraw`,它就会尝试发送以太币,但是因为 Faucet 没有以太币余额,所以会失败。
METoken 合约知道 Faucet 有余额,但是要转移这些余额唯一的办法就是让 Faucet 合约调用`METoken`的`transfer`函数。
下一步怎么办,没有办法了。发送给 Faucet 的 MET 永远卡住了。只有 Faucet 合约可以转移代币,但是 Faucet 合约没有调用 ERC20 代币合约的 transfer 函数的代码。
或许你已经预料到这个问题了,也有可能,你没有。事实上,数百名以太坊用户意外的将各种代币转移到没有 ERC20 功能的合约,据估计,这些代币价值超过250万美元(在写这篇文章时),已经像上面的例子一样永远被卡住,永远丢失了。
ERC20 代币用户在交易中无意丢失代币的一个原因,是他们试图将代币转移到一个交易所或者其他服务,以为可以简单的将代币发送到从交易所网站上复制的以太坊地址,然而,很多交易所发布的接收地址其实是一个合约!这些合约只接收以太币,而不是 ERC20 代币,通常这些资金会被清扫到他们的“冷藏库”或者其他中心化钱包。尽管很多警告说“不要将代币发送到这个地址”,依然有很多代币这样丢失。
## ERC20代币的问题
ERC20 标准的使用确实具有突破性,已经推出了上千种代币,既有新功能的实现,又有如众筹拍卖和ICO等各种资金筹集。然而,正如我们在前面向合约地址发送代币时所看到的,它有一些潜在风险。
ERC代币一个不太明显的问题,揭露了代币和以太币之间的细微差异。以太币是通过以接收地址为目标的交易进行转移的,代币转移发生在代币合约的状态中,以代币合约作为目标,而不是接收者的地址。代币合约跟踪余额并触发事件。在代币转移中,实际没有交易发送给代币接收者,接收者的地址只是被添加到代币合约的映射。向一个地址发送以太币的交易会改变地址状态。转移代币到一个地址的交易只会改变代币合约的状态,而不是接收者地址的状态。即使ERC20代币的钱包也不会知道代币余额,除非用户特地添加一个代币合约来“看”。一些钱包会“看”主流代币合约,来检查它们所控制的地址持有的余额,但是这仅限于现有ERC20合约的小部分。
事实上,用户并不会想要跟踪所有可能的ERC20代币合约的所有余额。很多ERC20代币更像是垃圾邮件,而不是可用的代币。为了吸引用户,他们会自动为有以太币活跃的账户创建余额。如果你有一个长期活跃的以太坊地址,尤其如果它是在预售中创建的,你就会发现它充满了不知从哪里冒出来的垃圾代币。当然,这个地址并不是真的充满了代币,那只是有你的地址的代币合约。只有在区块浏览器看到这些代币合约或者你的钱包查看你的地址时,你才会看到这些余额。
代币的行为方式与以太币不同。以太币是由send函数发送并且由合约中的payable函数或者外部地址接收。代币是用只存在于ERC20合约中的`transfer` 或 `approve` 和 `transferFrom` 函数发送,并且不会在接收合约触发任何payable函数(至少在ERC20中)。代币在功能上是像以太币一样的加密货币,但是他们的一些差异打破了这种幻想。
考虑另一个问题。要发送以太币或者使用任何以太坊合约,你需要以太币来支付gas。发送代币,你也需要以太币。你不能用代币为交易支付gas,并且代币合约也不能为你支付gas。这可能会在不久的将来有所改变,但同时也会导致一些奇怪的用户体验。
> 原文:[https://betterprogramming.pub/creating-erc20-token-on-ethereum-35e109dd96e0](https://betterprogramming.pub/creating-erc20-token-on-ethereum-35e109dd96e0)
本文通过创建一个代币深入讲解ERC20
图片来源: Undraw.co
ERC20代币标准
第一个标准由Fabian Vogelsteller于2015年11月以ethereum request for Comments(ERC)引入,它被自动分配到GitHub第20个议题,所以叫“ERC20代币”。目前绝大多数代币都基于ERC20标准。ERC20后来变成了以太坊改进提案20(EIP-20),但是大部分仍然使用它最初的名字,ERC20。
ERC20是一个同质化代币标准,意思是不同的ERC20代币是可互换的并且不具有独特属性。
ERC20标准为实现代币的合约定义了一个通用接口,这样任何兼容的代币都可以用同样的方式访问和使用。这个接口由许多必须在每次实现中都出现的函数构成,以及一些开发者可能添加的可选函数和属性。
ERC20需要的函数和事件
一个ERC20的代币合约必须至少提供下面这些函数和事件:
totalSupply: 返回当前代币总量,可以是一个固定值或者变量。
balanceOf:返回给定地址的代币余额
transfer: 从执行转账的地址余额中将指定数量的代币转移到指定地址。
transferFrom: 从一个账户到另一个账户,指定发送者,接收者和转移的代币数量。与approve结合使用。
approve: 指定一个被委托地址和委托代币数量,被委托地址可以在不超过委托数量的前提下多次从委托账户转移代币。
allowance: 给定一个所有者地址和一个被委托地址,返回被委托代币余额。
Transfer: 在成功转移(调用transfer或者transferFrom)后触发的事件(即使转移数量为0)。
Approval: 成功调用approve的事件日志。
ERC20 可选函数
name: 返回代币的可读名称(如“US Dollars”)。
symbol: 返回代币的可读符号(如“USD”)。
decimals: 返回代币数量的小数点位数。例如,如果decimals为2,表示小数点后2位。
ERC20 接口是用 Solidity 定义的。
下面是Solidity 的 ERC20接口规范:
contract ERC20 {
function totalSupply() constant returns (uint theTotalSupply);
function balanceOf(address _owner) constant returns (uint balance);
function transfer(address _to, uint _value) returns (bool success);
function transferFrom(address _from, address _to, uint _value) returns
(bool success);
function approve(address _spender, uint _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns
(uint remaining);
event Transfer(address indexed _from, address indexed _to, uint _value);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
ERC20 数据结构
如果你检查任何一个ERC20实现,你会发现它包含两个数据结构,一个用来跟踪余额(balance),另一个用来跟踪委托代币余额(allowance)。在Solidity中,都是用数据映射实现的。
第一个数据映射允许代币合约跟踪谁拥有代币。每次交易都是从一个余额扣除同时在另一个余额增加:
mapping(address => uint256) balances;
第二个数据结构是委托代币余额(allowance)的数据映射。正如我们将在下一节看到的,ERC20代币所有者可以让一个被委托者花费自己余额中一定数量的代币(allowance) 。
ERC20 合约用一个二维映射跟踪委托代币余额,其主键是代币所有者的地址,映射到被委托地址和对应的委托代币余额:
mapping (address => mapping (address => uint256)) public allowed;
ERC20工作流程:“transfer” 和 “approve + transferFrom”
ERC20代币标准有两个交易函数。你可能想知道为什么。
ERC20允许两种不同的工作流程。第一种是一笔交易,使用transfer函数的的简单流程。这个流程用于一个钱包发送代币到另一个钱包。
执行转账合约非常简单。如果Alice想要发送10个代币给Bob,她的钱包会发送一笔交易到代币合约的地址,调用transfer函数,并且参数为Bob的地址和10。代币合约修改Alice的余额(-10)和Bob的余额(+10),然后发出一个Transfer事件。
第二种流程是两笔交易,approve+transferFrom。这个流程允许代币所有者将控制权委托给另一个地址。通常用于将控制权委托给一个分配代币的合约,也可以被交易所使用。
例如,如果一个公司正在为ICO发售代币,他们可以委托一个众筹合约地址来分发一定数量的代币。这个众筹合约可以通过transferFrom将代币合约所有者的余额转给每一个代币买家,如下图所示。
注意:首次代币发行(ICO)是公司或者组织为了筹集资金而出售代币的众筹机制。这个术语源自首次公开募股(IPO),这是上市公司在证券交易所向投资者出售股票的过程。与高度监管的IPO市场不同,ICO是开放的、全球化的、混乱的。本文对ICO的示例和解释并非对此类筹款活动的认可。
ERC20 workflow
ERC20实现
虽然大约30行Solidity代码就可以实现一个ERC20代币,但大部分的实现都是更复杂的。这是为了解决潜在的漏洞。EIP-20标准提到两种实现:
Consensys EIP20 —— 一种简单且易读的ERC20代币的实现。
OpenZeppelin StandardToken —— 这个实现兼容ERC20,并且有额外安全措施。它形成了OpenZeppelin库的基础,可以实现更复杂ERC20代币,如筹款上限,拍卖,期权等功能。
发起自己的ERC20代币
接下来我们创建并发起自己的代币。下面的例子,将使用Truffle框架。假设你已经安装了Truffle,如果没有安装,请用npm安装:
npm i truffle
假设我们的代币叫“Mastering Ethereum Token”,我们用符号“MET”代表它。
注意:你可以在这里找到这个例子。
首先,我们创建并初始化一个Truffle项目目录。运行下面4个命令并接受所有默认答案:
$ mkdir METoken
$ cd METoken
METoken $ truffle init
METoken $ npm init
你现在应该有下面的目录结构了:
METoken/
+---- contracts
| `---- Migrations.sol
+---- migrations
| `---- 1_initial_migration.js
+---- package.json
+---- test
`---- truffle-config.js
编辑truffle-config.js配置文件,配置Truffle环境,或者复制下面的示例:
// Install dependencies:
// npm init
// npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet
// Create .env in project root, with keys:
// ROPSTEN_PRIVATE_KEY="123abc"
// MAINNET_PRIVATE_KEY="123abc"
require('dotenv').config();
const Web3 = require("web3");
const web3 = new Web3();
const WalletProvider = require("truffle-wallet-provider");
const Wallet = require('ethereumjs-wallet');
var mainNetPrivateKey = new Buffer(process.env["MAINNET_PRIVATE_KEY"], "hex")
var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");
var ropstenPrivateKey = new Buffer(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");
module.exports = {
networks: {
dev: { // Whatever network our local node connects to
network_id: "*", // Match any network id
host: "localhost",
port: 8545,
},
mainnet: { // Provided by Infura, load keys in .env file
network_id: "1",
provider: mainNetProvider,
gas: 4600000,
gasPrice: web3.utils.toWei("20", "gwei"),
},
ropsten: { // Provided by Infura, load keys in .env file
network_id: "3",
provider: ropstenProvider,
gas: 4600000,
gasPrice: web3.utils.toWei("20", "gwei"),
},
kovan: {
network_id: 42,
host: "localhost", // parity --chain=kovan
port: 8545,
gas: 5000000
},
ganache: { // Ganache local test RPC blockchain
network_id: "5777",
host: "localhost",
port: 7545,
gas: 6721975,
}
}
};
-truffle-config.js-
如果你用示例truffle-config.js,记住在包含你的测试私钥的METoken文件夹中创建一个.env文件,以便在以太坊公共测试网(如Ropsten or Kovan)上部署和测试。你可以从 MetaMask 导出测试网私钥。
这时,你的目录应该是这样的:
METoken/
+---- contracts
| `---- Migrations.sol
+---- migrations
| `---- 1_initial_migration.js
+---- package.json
+---- test
+---- truffle-config.js
`---- .env *new file*
警告
只能使用没有在以太坊主网上持有资产的测试密钥或者测试助记词。切勿将真正持有资产的密钥用于测试。
在我们的示例中,我们将导入 OpenZeppelin 库,这个库实现了一些重要的安全检查并且容易扩展:
$ npm install openzeppelin-solidity@1.12.0
+ openzeppelin-solidity@1.12.0
added 1 package from 1 contributor and audited 2381 packages in 4.074s
openzeppelin-solidity包会在node_modules目录下添加大约250个文件。OpenZeppelin库并不仅仅包含ERC20代币,我们只会使用其中一小部分。
接下来,开始写代币合约。创建一个新文件,METoken.sol,并从下面复制示例代码。
pragma solidity ^0.4.21;
import 'openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol';
contract METoken is StandardToken {
string public constant name = 'Mastering Ethereum Token';
string public constant symbol = 'MET';
uint8 public constant decimals = 2;
uint constant _initial_supply = 2100000000;
function METoken() public {
totalSupply_ = _initial_supply;
balances[msg.sender] = _initial_supply;
emit Transfer(address(0), msg.sender, _initial_supply);
}
}
-METoken.sol-
METoken.sol合约——实现ERC20代币的Solidity合约,非常简单,因为它从OpenZeppelin库继承了所有功能。
示例 1. METoken.sol: 实现ERC20代币的Solidity合约
这里,我们定义了可选变量名,符号,和小数位数,也定义了一个_initial_supply变量——设为2100万个代币,代币数量可以细分到小数点后2位,也就是总共21亿份。在合约的初始化函数(构造函数)中我们设置totalSupply等于_initial_supply,并且将所有_initial_supply全部分配给创建METoken合约的账户(msg.sender)的余额。
现在我们用truffle来编译METoken代码:
$ truffle compile
Compiling ./contracts/METoken.sol...
Compiling ./contracts/Migrations.sol...
Compiling openzeppelin-solidity/contracts/math/SafeMath.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/BasicToken.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol...
Compiling openzeppelin-solidity/contracts/token/ERC20/StandardToken.sol...
如你所见,truffle 编译了 OpenZeppelin 库的必要依赖。
接下来我们编写一个迁移脚本来部署METoken合约。在METoken/migrations 文件夹中创建一个新文件2_deploy_contracts.js。复制下面示例代码:
var METoken = artifacts.require("METoken");
module.exports = function(deployer) {
// Deploy the METoken contract as our only task
deployer.deploy(METoken);
};
-2_deploy_contracts.js-
在部署到以太坊测试网之前,我们先启动一个本地区块链来测试。可以从命令行ganache-cli 或者图形用户界面来启动ganache区块链。
ganache 启动,我们就可以部署 METoken 合约并且看到是否一切正常:
$ truffle migrate --network ganache
Using network 'ganache'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0xb2e90a056dc6ad8e654683921fc613c796a03b89df6760ec1db1084ea4a084eb
Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0
Saving successful migration to network...
... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956
Saving artifacts...
Running migration: 2_deploy_contracts.js
Deploying METoken...
... 0xbe9290d59678b412e60ed6aefedb17364f4ad2977cfb2076b9b8ad415c5dc9f0
METoken: 0x345ca3e014aaf5dca488057592ee47305d9b3e10
Saving successful migration to network...
... 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0
Saving artifacts...
在 ganache 控制台,我们可以看到已经创建了四笔新的交易:
-ganache-
用 Truffle 控制台与 METoken 交互
我们可以通过 truffle 控制台在 ganache 区块链上与合约交互。这是一个交互式 JavaScript 环境,提供了对 truffle 环境的访问,并通过 web3 访问区块链。下面,我们将 truffle 控制台与 ganache 区块链连接:
$ truffle console --network ganache
truffle(ganache)>
truffle(ganache)>表明我们已经连接到 ganache 区块链,并且已经准备好输入命令。truffle 控制台支持所有 truffle 命令,所以我们可以从控制台编译和迁移。
我们已经运行了命令,所以让我们直接进入到合约本身。METoken合约在 truffle 环境中就像一个 JavaScript 对象。在提示符的地方输入METoken,就会清除整个合约定义:
truffle(ganache)> METoken
{ [Function: TruffleContract]
_static_methods:
[...]
currentProvider:
HttpProvider {
host: 'http://localhost:7545',
timeout: 0,
user: undefined,
password: undefined,
headers: undefined,
send: [Function],
sendAsync: [Function],
_alreadyWrapped: true },
network_id: '5777' }
METoken对象也揭露了几个属性,如合约地址(因为是用 migrate 命令部署的):
truffle(ganache)> METoken.address
'0x345ca3e014aaf5dca488057592ee47305d9b3e10'
如果我们想要与部署的合约交互,我们必须使用异步调用,以JavaScript “promise” 的形式。用 deployed 函数来获取合约实例,然后调用totalSupply函数:
truffle(ganache)> METoken.deployed().then(instance => instance.totalSupply())
BigNumber { s: 1, e: 9, c: [ 2100000000 ] }
接下来,让我们用 ganache 创建的账户来检查 METoken 余额,并且发送一些 METoken 到另一个地址。首先,获取账户地址:
truffle(ganache)> let accounts
undefined
truffle(ganache)> web3.eth.getAccounts((err,res) => { accounts = res })
undefined
truffle(ganache)> accounts[0]
'0x627306090abab3a6e1400e9345bc60c78a8bef57'
账户列表包含 ganache 创建的所有账户,accounts[0]是部署METoken合约的账户。它应该有METoken余额的,因为我们的METoken构造函数将所有token给到了这个地址。我们检查一下:
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(accounts[0]).then(console.log) })
undefined
truffle(ganache)> BigNumber { s: 1, e: 9, c: [ 2100000000 ] }
最后,通过调用合约的transfer函数从accounts[0]转移 1000.00 个 METoken 到accounts[1]:
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.transfer(accounts[1], 100000) })
undefined
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(accounts[0]).then(console.log) })
undefined
truffle(ganache)> BigNumber { s: 1, e: 9, c: [ 2099900000 ] }
undefined
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(accounts[1]).then(console.log) })
undefined
truffle(ganache)> BigNumber { s: 1, e: 5, c: [ 100000 ] }
提示:METoken可以精确到小数点后2位,意思是1个METoken在合约中其实是100份。当我们转移1000个METoken时,我们在调用transfer函数时指定的值是100000
如你所见,在会话中,accounts[0]现在有20,999,000 个MET,accounts[1]有1000个MET。
-ganache-
向合约地址发送ERC20代币
到目前为止,我们已经创建了一个ERC20代币并从一个账户发送了一些代币到另一个账户。前面我们用来演示的账户都是外部账户(external owned accouts),意思是由私钥控制的账户,不是一个合约。如果我们发送 MET 到一个合约地址又会发生什么呢?
首先,我们在测试环境部署另一个合约。这个例子,我们将直接用水龙头合约Faucet.sol。将它复制到contracts 目录下,这样就把它添加到 METoken 项目下。现在目录是这样的:
METoken/
+---- contracts
| +---- Faucet.sol
| +---- METoken.sol
| `---- Migrations.sol
还要再添加一个迁移,将Faucet和METoken分开部署:
var Faucet = artifacts.require("Faucet");
module.exports = function(deployer) {
// Deploy the Faucet contract as our only task
deployer.deploy(Faucet);
};
在 truffle 控制台编译并迁移合约:
$ truffle console --network ganache
truffle(ganache)> compile
Compiling ./contracts/Faucet.sol...
Writing artifacts to ./build/contracts
truffle(ganache)> migrate
Using network 'ganache'.
Running migration: 1_initial_migration.js
Deploying Migrations...
... 0x89f6a7bd2a596829c60a483ec99665c7af71e68c77a417fab503c394fcd7a0c9
Migrations: 0xa1ccce36fb823810e729dce293b75f40fb6ea9c9
Saving artifacts...
Running migration: 2_deploy_contracts.js
Replacing METoken...
... 0x28d0da26f48765f67e133e99dd275fac6a25fdfec6594060fd1a0e09a99b44ba
METoken: 0x7d6bf9d5914d37bcba9d46df7107e71c59f3791f
Saving artifacts...
Running migration: 3_deploy_faucet.js
Deploying Faucet...
... 0x6fbf283bcc97d7c52d92fd91f6ac02d565f5fded483a6a0f824f66edc6fa90c3
Faucet: 0xb18a42e9468f7f1342fa3c329ec339f254bc7524
Saving artifacts...
赞,现在我们向 Faucet 合约发送 MET :
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.transfer(Faucet.address, 100000) })
truffle(ganache)> METoken.deployed().then(instance =>
{ instance.balanceOf(Faucet.address).then(console.log)})
truffle(ganache)> BigNumber { s: 1, e: 5, c: [ 100000 ] }
我们已经将 1000MET 转给了 Faucet 合约。现在,我们要如何取出这些代币呢?
记住,Faucet.sol是一个非常简单的合约。它只有一个用来提取以太币的函数withdraw,没有用来提取 MET 的函数,或者任何其他 ERC20 代币。如果我们用withdraw,它就会尝试发送以太币,但是因为 Faucet 没有以太币余额,所以会失败。
METoken 合约知道 Faucet 有余额,但是要转移这些余额唯一的办法就是让 Faucet 合约调用METoken的transfer函数。
下一步怎么办,没有办法了。发送给 Faucet 的 MET 永远卡住了。只有 Faucet 合约可以转移代币,但是 Faucet 合约没有调用 ERC20 代币合约的 transfer 函数的代码。
或许你已经预料到这个问题了,也有可能,你没有。事实上,数百名以太坊用户意外的将各种代币转移到没有 ERC20 功能的合约,据估计,这些代币价值超过250万美元(在写这篇文章时),已经像上面的例子一样永远被卡住,永远丢失了。
ERC20 代币用户在交易中无意丢失代币的一个原因,是他们试图将代币转移到一个交易所或者其他服务,以为可以简单的将代币发送到从交易所网站上复制的以太坊地址,然而,很多交易所发布的接收地址其实是一个合约!这些合约只接收以太币,而不是 ERC20 代币,通常这些资金会被清扫到他们的“冷藏库”或者其他中心化钱包。尽管很多警告说“不要将代币发送到这个地址”,依然有很多代币这样丢失。
ERC20代币的问题
ERC20 标准的使用确实具有突破性,已经推出了上千种代币,既有新功能的实现,又有如众筹拍卖和ICO等各种资金筹集。然而,正如我们在前面向合约地址发送代币时所看到的,它有一些潜在风险。
ERC代币一个不太明显的问题,揭露了代币和以太币之间的细微差异。以太币是通过以接收地址为目标的交易进行转移的,代币转移发生在代币合约的状态中,以代币合约作为目标,而不是接收者的地址。代币合约跟踪余额并触发事件。在代币转移中,实际没有交易发送给代币接收者,接收者的地址只是被添加到代币合约的映射。向一个地址发送以太币的交易会改变地址状态。转移代币到一个地址的交易只会改变代币合约的状态,而不是接收者地址的状态。即使ERC20代币的钱包也不会知道代币余额,除非用户特地添加一个代币合约来“看”。一些钱包会“看”主流代币合约,来检查它们所控制的地址持有的余额,但是这仅限于现有ERC20合约的小部分。
事实上,用户并不会想要跟踪所有可能的ERC20代币合约的所有余额。很多ERC20代币更像是垃圾邮件,而不是可用的代币。为了吸引用户,他们会自动为有以太币活跃的账户创建余额。如果你有一个长期活跃的以太坊地址,尤其如果它是在预售中创建的,你就会发现它充满了不知从哪里冒出来的垃圾代币。当然,这个地址并不是真的充满了代币,那只是有你的地址的代币合约。只有在区块浏览器看到这些代币合约或者你的钱包查看你的地址时,你才会看到这些余额。
代币的行为方式与以太币不同。以太币是由send函数发送并且由合约中的payable函数或者外部地址接收。代币是用只存在于ERC20合约中的transfer 或 approve 和 transferFrom 函数发送,并且不会在接收合约触发任何payable函数(至少在ERC20中)。代币在功能上是像以太币一样的加密货币,但是他们的一些差异打破了这种幻想。
考虑另一个问题。要发送以太币或者使用任何以太坊合约,你需要以太币来支付gas。发送代币,你也需要以太币。你不能用代币为交易支付gas,并且代币合约也不能为你支付gas。这可能会在不久的将来有所改变,但同时也会导致一些奇怪的用户体验。
原文:https://betterprogramming.pub/creating-erc20-token-on-ethereum-35e109dd96e0
学分: 171
分类: 以太坊
标签:
ERC20
智能合约
代币
点赞 5
收藏 3
分享
Twitter分享
微信扫码分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
你可能感兴趣的文章
星航计划 - DeTask找活网 0基础开发入门到精通 (9)
90 浏览
1.轻松入门Sui Move: 快速了解基本概念
98 浏览
SharkTeam:合约精度计算漏洞与安全建议
379 浏览
Remix v0.43.0 更新日志
209 浏览
使用铭文思路对智能合约改进
2141 浏览
花式发币法之发行各类 ERC20 代币
3968 浏览
相关问题
请问智能合约是究竟怎么在以太坊上运行的?
1 回答
请教下大家,Swap如何实现卖币手续费
2 回答
关于交易字段内容的问题
1 回答
地址部署合约部署失败,但是换个地址部署相同的合约代码可以部署成功,详细描述如下,麻烦各位大佬帮忙分析分析原因
1 回答
如何将合约字节码反编译成solidity伪代码
1 回答
Foundry Test: 无效的 MockCall
3 回答
3 条评论
请先 登录 后评论
aisiji
关注
贡献值: 228
学分: 1344
江湖只有他的大名,没有他的介绍。
文章目录
关于
关于我们
社区公约
学分规则
Github
伙伴们
DeCert
ChainTool
GCC
合作
广告投放
发布课程
联系我们
友情链接
关注社区
Discord
Youtube
B 站
公众号
关注不错过动态
微信群
加入技术圈子
©2024 登链社区 版权所有 |
Powered By Tipask3.5|
粤公网安备 44049102496617号
粤ICP备17140514号
粤B2-20230927
增值电信业务经营许可证
×
发送私信
请将文档链接发给晓娜,我们会尽快安排上架,感谢您的推荐!
发给:
内容:
取消
发送
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
取消
举报
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!