ERC721 has both safeTransferFrom and transferFrom, where safeTransferFrom throws if the receiving contract's onERC721Received method doesn't return a specific magic number. This is to ensure a receiving contract is capable of receiving the token, so it isn't permanently lost.

But why would transferFrom exist too when it doesn't have this check? My only guess it to make ERC721 compatible with ERC20, which has a transferFrom method with the same signature. However the semantics of the method in each standard are different (the uint256 in ERC20 refers to the value, whereas in ERC721 it refers to the tokenID) so compatibility there seems misleading.

What am I missing?

  • There is a strong argument for not using safeTransferFrom at all. There are other mechanisms for providing the necessary safety. And tbh there was not enough consensus in 2018 to coalesce around that. So now we have both and you are free to use either or both. Apr 17, 2021 at 18:16

3 Answers 3


There is an explanation in the original Github ERC721 thread about keeping the "unsafe" transfer function (comment from Dieter Shirley, alias "dete", one of the authors of EIP-721) :

Upon further reflection and discussion with @flockonus, we are proposing to keep a straightforward (and therefore "unsafe") transfer() method. (i.e. It would work like ERC-20, and not EIP-223.)

Our reasoning is as follows:

  • Simpler is always better for standards. The fewer requirements, the harder it is to screw it up. (And NFTs are already complicated enough!)
  • It is not the job of a smart contract to protect against every possible user error (it must protect against invalid actions, not unintended actions). In particular, the case we are trying to avoid (sending NFTs to contracts that don't know how to handle them) is better served by checks and warnings in the wallet software. A wallet (or other smart contract interface) will always be able to have more robust and dynamic checks than a smart contract, and is also able to engage in some "back-and-forth" dialog with the user. Smart contracts don't have the equivalent of a "This seems unsafe, are you sure?" dialog box!

This functionality has therefore been retained for greater flexibility and to keep the standard as simple as possible.


There is an explanation in the ERC721.sol that the caller is responsible to confirm that the recipient is capable of receiving ERC721 or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must understand this adds an external call which potentially creates a reentrancy vulnerability.

So, safeTransferFrom is safe to use but reentrancy may happen...


The transferFrom method in both ERC20 and ERC721 is used to transfer tokens from one account to another. However, as you noted, the semantics of the method in each standard are different.

In ERC20, the uint256 argument is the amount of tokens to transfer, which makes sense because all tokens are identical.

In ERC721, the uint256 argument is the unique identifier for the token to transfer, which makes sense because each token is unique.

The safeTransferFrom method in ERC721 was introduced to add an additional layer of safety. When you transfer a token to a contract, the contract can implement the onERC721Received function to react to the transfer. If the contract does not return the correct magic value from onERC721Received, then safeTransferFrom will revert the transaction. This is to prevent tokens from being accidentally lost by being transferred to contracts that are not designed to handle them.

So why does transferFrom exist in ERC721? There could be several reasons:

Backwards compatibility: ERC721 was designed to be a superset of the ERC20 interface, which includes transferFrom.

Flexibility: transferFrom gives more flexibility to developers. They can decide whether they want to use transferFrom or safeTransferFrom based on their specific use case.

Gas costs: transferFrom can be cheaper in terms of gas because it doesn't require a call to onERC721Received.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.