在使用transfer 和 send 方法的是后需要关注一下 receive方法和callback方法。
receive 接收以太函数
- 一个合约最多有一个
receive
函数, 声明函数为:receive() external payable { ... }
- 不需要
function
关键字,也没有参数和返回值并且必须是external
可见性和payable
修饰. 它可以是virtual
的,可以被重载也可以有 修改器modifier 。 - 在对合约没有任何附加数据调用(通常是对合约转账)是会执行
receive
函数. 例如 通过.send()
or.transfer()
如果receive
函数不存在, 但是有payable 的 fallback 回退函数fallback 回退函数fallback 回退函数 那么在进行纯以太转账时,fallback 函数会调用. - 如果两个函数都没有,这个合约就没法通过常规的转账交易接收以太(会抛出异常).
- 更糟的是,
receive
函数可能只有 2300 gas 可以使用(如,当使用send
或transfer
时), 除了基础的日志输出之外,进行其他操作的余地很小。
Fallback 回退函数
- 合约可以最多有一个回退函数。函数声明为:
fallback () external [payable]
或fallback (bytes calldata _input) external [payable] returns (bytes memory _output)
- 没有
function
关键字。 必须是external
可见性,它可以是virtual
的,可以被重载也可以有 修改器modifier 。 - 如果在一个对合约调用中,没有其他函数与给定的函数标识符匹配fallback会被调用. 或者在没有 receive 函数
时,而没有提供附加数据对合约调用,那么fallback 函数会被执行。 - fallback 函数始终会接收数据,但为了同时接收以太时,必须标记为
payable
。 - 如果使用了带参数的版本,
_input
将包含发送到合约的完整数据(等于msg.data
),并且通过_output
返回数据。 返回数据不是 ABI 编码过的数据,相反,它返回不经过修改的数据。 - 更糟的是,如果回退函数在接收以太时调用,可能只有 2300 gas 可以使用,参考 receive接收函数
- 与任何其他函数一样,只要有足够的 gas 传递给它,回退函数就可以执行复杂的操作。