1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| // ERC777 定义的转账函数, 同时触发 ERC20的 `Transfer` 事件 function send(address recipient, uint256 amount, bytes calldata data) external { _send(msg.sender, msg.sender, recipient, amount, data, "", true); } // 转移代币,需要有操作者权限,触发 `Sent` 和 `Transfer` 事件 function operatorSend( address sender, address recipient, uint256 amount, bytes calldata data, bytes calldata operatorData ) external { require(isOperatorFor(msg.sender, sender), "ERC777: caller is not an operator for holder"); _send(msg.sender, sender, recipient, amount, data, operatorData, true); } // 为兼容 ERC20,同时触发 `Sent` 事件 function transfer(address recipient, uint256 amount) external returns (bool) { require(recipient != address(0), "ERC777: transfer to the zero address");
address from = msg.sender;
_callTokensToSend(from, from, recipient, amount, "", "");
_move(from, from, recipient, amount, "", "");
//最后一个参数表示不要求接收者实现钩子函数 `tokensReceived` _callTokensReceived(from, from, recipient, amount, "", "", false);
return true; } // 转移 token // 最后一个参数 requireReceptionAck 表示是否必须实现 ERC777TokensRecipient function _send( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData, bool requireReceptionAck ) private { require(from != address(0), "ERC777: send from the zero address"); require(to != address(0), "ERC777: send to the zero address");
// 在修改余额状态之前调用tokensToSend _callTokensToSend(operator, from, to, amount, userData, operatorData);
// 修改余额状态 _move(operator, from, to, amount, userData, operatorData);
// 在修改余额状态之后调用tokensReceived _callTokensReceived(operator, from, to, amount, userData, operatorData, requireReceptionAck); }
// 转移所有权 function _move( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData ) private { _balances[from] = _balances[from].sub(amount); _balances[to] = _balances[to].add(amount);
emit Sent(operator, from, to, amount, userData, operatorData); emit Transfer(from, to, amount); } // 尝试调用持有者的 tokensToSend() 函数 // 如果持有者有通过 ERC1820 注册 ERC777TokensSender 实现接口, 代币合约必须调用其 tokensToSend 钩子函数 function _callTokensToSend( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData ) private { address implementer = _erc1820.getInterfaceImplementer(from, TOKENS_SENDER_INTERFACE_HASH); if (implementer != address(0)) { IERC777Sender(implementer).tokensToSend(operator, from, to, amount, userData, operatorData); } }
// 尝试调用接收者的 tokensReceived() // 如果接收者有通过 ERC1820 注册 ERC777TokensRecipient 实现接口, 代币合约必须调用其 tokensReceived 钩子函数。 function _callTokensReceived( address operator, address from, address to, uint256 amount, bytes memory userData, bytes memory operatorData, bool requireReceptionAck ) private { address implementer = _erc1820.getInterfaceImplementer(to, TOKENS_RECIPIENT_INTERFACE_HASH); if (implementer != address(0)) { IERC777Recipient(implementer).tokensReceived(operator, from, to, amount, userData, operatorData); } else if (requireReceptionAck) { // 如果接收者是一个合约地址, 则必须要注册及实现 ERC777TokensRecipient 接口(这样可以防止代币被锁死),如果没有实现,ERC777代币合约必须revert 回退交易状态 require(!to.isContract(), "ERC777: token recipient contract has no implementer for ERC777TokensRecipient"); } }
|