本文主要记录fallback、receive函数,比对这两个函数的区别,onERC721Received含义
fallback&&receive
receive
fallback和receive是相似的,首先是receive,接收以太的函数
定义: receive() external payable{
}
一个合约可以有0个或者1个 receive函数,并且该函数需要被定义为external payable,他可以是virtual,被重载并且有modifier
当给合约转账时,msg.sender.call/msg.sender.send/msg.sender.transfer时,如果不传输任何数据,如果calldata(msg.data)为空,则会看`reveive()`函数是否存在
- `receive()`最好不要执行太多的逻辑因为如果用send和transfer方法发送ETH的话,gas会限制在2300,`receive()`太复杂可能会触发Out of Gas报错
fallback
fallback和receive是相似的,fallback,接收以太的函数
定义: fallback() external payable{
}
一个合约可以有0个或者1个 fallback函数,并且该函数需要被定义为external payable,他可以是virtual,被重载并且有modifier
当给合约转账时,msg.sender.call/msg.sender.send/msg.sender.transfer时,如果传输数据,calldata(msg.data)不为空,则会执行fallback函数
如果calldata为空,receive不存在,则执行fallback
只要有足够的 gas 传递给它,回退函数就可以执行复杂的操
onERC721Received
IERC721Receiver是一个接口(interface),一个合约必须实现这个接口才可以收到ERC721标准(NFT)的Token,用于安全转账中对合约地址的检查
接收nft(token)的合约需要实现这个接口
// 接收 ERC721 NFT
function onERC721Received(
address,
address from,
uint256 tokenId,
bytes calldata
) external pure override returns (bytes4) {
return this.onERC721Received.selector;
}
当我执行转账方法,转账nft到该账户,我需要先进行校验,验证这个合约账户是可以接收nft的,验证逻辑如下:
// 检查被授权者是否接收 NFT
function _checkOnERC721Received(
address from,
address to,
bytes memory _data
) internal returns (bool) {
// 如果被授权者不是合约则表示接收成功
if (to.code.length == 0) {
return true;
}
// 调用被授权者的 onERC721Received 函数
try
IERC721Receiver(to).onERC721Received(
msg.sender,
from,
totalSupply,
_data
)
returns (bytes4 retval) {
// 如果返回值为 ERC721_RECEIVED 则表示接收成功
return retval == IERC721Receiver(to).onERC721Received.selector;
} catch (bytes memory reason) {
// 如果调用失败则表示接收失败
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
assembly {
revert(add(32, reason), mload(reason))
}
}
}
}