ERC777介绍
简介
ERC777保持与 ERC20 兼容。
操作员通常利用合约发送token,并具备发送 / 接收钩子,以使得持有者对其token拥有更多的控制权。
它利用 ERC1820 来了解在合同和用户地址收到token时是否以及在何处通知它们。
解决的问题(相对于ERC20的优点)
- 同样使用
send(dest, value, data)
发送Ether - 使用
tokensToSend
钩子,合约和用户地址都可以控制和拒绝发送出去的token - 使用
tokensReceived
钩子,合约和用户地址都可以控制和拒绝接收到的token tokensReceived
钩子允许发送token到合约地址,并在交易中心发出通知。而ERC20需要approve/transferFrom
两次调用才能达到这样的效果- token持有人可以指定/去除操作员(合约)地址,这些操作员通常是已经验证过的合约contract,例如交易所,支票处理器或自动收费系统
- 每一笔交易含有
data
和operatorData
,它们是bytes字段,在token持有人和操作员之间传递信息 tokensReceived
钩子函数可以通过代理合约来部署,所以ERC777是与ERC20钱包兼容的
构建ERC777合约
1 | pragma solidity ^0.5.0; |
ERC777扩展了ERC20,对ERC20提供兼容性支持。使用 _mint
将 initialSupply
分配给部署者帐户。与ERC20的_mint不同,此参数包含一些额外的参数,但是可以放心地忽略它们。
initialSupply
没有设定小数。ERC777规定小数始终返回固定值18,因此无需自行设置。
最后,我们需要设置defaultOperators:操作员帐户(通常是智能合约地址),该帐户将能够代表其持有者转让token。如果不打算在token中使用操作员(合约),则只需传递一个空数组即可。
基本的ERC777合约就是这样! 现在,对其进行部署,并使用相同的balanceOf方法来查询部署者的余额:
1 | GLDToken.balanceOf(deployerAddress) |
要将token从一个帐户转移到另一个帐户,既可以使用ERC20的“transfer”方法,也可以使用新的ERC777的“send”方法,其作用非常相似,但是增加了一个可选的data
字段:
1 | GLDToken.transfer(otherAddress, 300) |
ERC777接口定义如下:
1 | interface ERC777Token { |
钩子函数如何工作
首先来了解一下 ERC1820, ERC1820是一个全局的合约,在以太坊链上有一个唯一的合约地址,它总是 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
。
ERC1820 合约提过了两个主要接口:
setInterfaceImplementer(address _addr, bytes32 _interfaceHash, address _implementer)
用来设置地址(_addr)的接口(_interfaceHash 接口名称的 keccak256 )由哪个合约实现(_implementer)。getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address)
这个函数用来查询地址(_addr)的接口由哪个合约实现。
ERC777 使用 send
转账时,会分别在持有者和接收者地址上使用 ERC1820 的 getInterfaceImplementer 函数进行查询,查看是否有对应的实现合约,ERC777 标准规范里预定了接口及函数名称,如果有实现则进行相应的调用。
ERC777 使用 operatorSend
转账时,可以通过参数operatorData
携带操作者的信息,发送代币除了执行对应账户的余额加减和触发事件之外,还有额外的规定:
- 如果持有者有通过 ERC1820 注册
ERC777TokensSender
实现接口,代币合约必须调用其tokensToSend
钩子函数。 - 如果接收者有通过 ERC1820 注册
ERC777TokensRecipient
实现接口, 代币合约必须调用其tokensReceived
钩子函数。 - 如果有
tokensToSend
钩子函数,必须在修改余额状态之前调用。 - 如果有
tokensReceived
钩子函数,必须在修改余额状态之后调用。 - 调用钩子函数及触发事件时,
data
和operatorData
必须原样传递,因为 tokensToSend 和 tokensReceived 函数可能根据这个数据取消转账(触发revert
)。
从而保证了ERC777交易以及钩子函数的原子性。
参考链接 ==>
https://eips.ethereum.org/EIPS/eip-777
https://github.com/0xjac/ERC777