function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory _data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
return retval == IERC721Receiver.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))
}
}
}
} else {
return true;
}
}
1 Answer
If is usually called after a token has been transferred (in same tx).
If the receiver of the token is a contract, it checks if the contract implements the onERC721Received interface.
If no, it reverts the transaction.
If yes, the receiver contract has a onERC721Received
method. The ERC721 calls this method, and now execution goes to the receiver contract to do whatever he wants. For example - staking the received token. [or more dangerously - reenter the ERC721 contarct.]
After the receiver token's onERC721Received
finishes, the execution resumes in the ERC721 contract.