Hi there,
As I was writing both ERC20 and ERC721 lately, I found out that in ERC20, functions like transfer, approve and transferFrom return the boolean value true, whereas in ERC721, the same functions don’t return any boolean value.
Can anyone please tell me if they should return true or not? Can OpenZeppelin double check on their implementations? I bet more consistency is always more favorable.
Besides, inconsistencies also happen at how input variables are cannotated: for example, in ERC20, variables like from, to have a postfix underscore, i.e., from_, to_, whereas in ERC721, the postfix is not added. Is there a reason for this as well?
Cheers!
1 Like
Hi @maxareo ,
OpenZeppelin Contracts token implementations should follow the EIP.
ERC20 transfer returns a boolean:
https://eips.ethereum.org/EIPS/eip-20
ERC721 transfer doesn't return:
https://eips.ethereum.org/EIPS/eip-721
There may be inconsistencies between the EIPs.
maxareo:
Besides, inconsistencies also happen at how input variables are cannotated: for example, in ERC20, variables like from, to have a postfix underscore, i.e., from_, to_, whereas in ERC721, the postfix is not added. Is there a reason for this as well?
Can you give an example of inconsistencies in the OpenZeppelin Contracts implementations?
I couldn't find from_
or to_
in the following:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "./extensions/IERC721Enumerable.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
This file has been truncated. show original
I figured out that the postfixes are only used in constructors, so it may not be an issue at all.
constructor (string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
Here as well:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC721.sol";
import "./IERC721Receiver.sol";
import "./extensions/IERC721Metadata.sol";
import "../../utils/Address.sol";
import "../../utils/Context.sol";
import "../../utils/Strings.sol";
import "../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/
contract ERC721 is Context, ERC165, IERC721, IERC721Metadata {
using Address for address;
using Strings for uint256;
This file has been truncated. show original
1 Like
Hi @maxareo ,
I assume this is to avoid clashes with the getter functions for name
and symbol
and the private state variables _name
and _symbol
I see. That makes sense. There is a legitimate reason beyond a naming convention. Thanks.
1 Like