Fallback、Receive、IERC721.onERC721Received

183 阅读2分钟

本文主要记录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))
              }
          }
      }
  }