forked from ethereum/EIPs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
function balanceOf(...)
(ethereum#5172)
- ... as flat file reference implementation
- Loading branch information
1 parent
617322f
commit a94cd0a
Showing
8 changed files
with
192 additions
and
311 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
// SPDX-License-Identifier: CC0-1.0 | ||
pragma solidity ^0.8.6; | ||
|
||
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) | ||
|
||
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) | ||
|
||
/** | ||
* @dev Interface of the ERC165 standard, as defined in the | ||
* https://eips.ethereum.org/EIPS/eip-165[EIP]. | ||
* | ||
* Implementers can declare support of contract interfaces, which can then be | ||
* queried by others ({ERC165Checker}). | ||
* | ||
* For an implementation, see {ERC165}. | ||
*/ | ||
interface IERC165 { | ||
/** | ||
* @dev Returns true if this contract implements the interface defined by | ||
* `interfaceId`. See the corresponding | ||
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] | ||
* to learn more about how these ids are created. | ||
* | ||
* This function call must use less than 30 000 gas. | ||
*/ | ||
function supportsInterface(bytes4 interfaceId) external view returns (bool); | ||
} | ||
|
||
/** | ||
* @dev Implementation of the {IERC165} interface. | ||
* | ||
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check | ||
* for the additional interface id that will be supported. For example: | ||
* | ||
* ```solidity | ||
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { | ||
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); | ||
* } | ||
* ``` | ||
* | ||
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. | ||
*/ | ||
abstract contract ERC165 is IERC165 { | ||
/** | ||
* @dev See {IERC165-supportsInterface}. | ||
*/ | ||
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { | ||
return interfaceId == type(IERC165).interfaceId; | ||
} | ||
} | ||
|
||
interface IERC721Metadata { | ||
function name() external view returns (string memory); | ||
function symbol() external view returns (string memory); | ||
function tokenURI(uint256 tokenId) external view returns (string memory); | ||
} | ||
|
||
/// @title Account-bound tokens | ||
/// @dev See https://eips.ethereum.org/EIPS/eip-4973 | ||
/// Note: the ERC-165 identifier for this interface is 0x5164cf47. | ||
interface IERC4973 /* is ERC165, ERC721Metadata */ { | ||
/// @dev This emits when a new token is created and bound to an account by | ||
/// any mechanism. | ||
/// Note: For a reliable `from` parameter, retrieve the transaction's | ||
/// authenticated `from` field. | ||
event Attest(address indexed to, uint256 indexed tokenId); | ||
/// @dev This emits when an existing ABT is revoked from an account and | ||
/// destroyed by any mechanism. | ||
/// Note: For a reliable `from` parameter, retrieve the transaction's | ||
/// authenticated `from` field. | ||
event Revoke(address indexed to, uint256 indexed tokenId); | ||
/// @notice Count all ABTs assigned to an owner | ||
/// @dev ABTs assigned to the zero address are considered invalid, and this | ||
/// function throws for queries about the zero address. | ||
/// @param owner An address for whom to query the balance | ||
/// @return The number of ABTs owned by `owner`, possibly zero | ||
function balanceOf(address owner) external view returns (uint256); | ||
/// @notice Find the address bound to an ERC4973 account-bound token | ||
/// @dev ABTs assigned to zero address are considered invalid, and queries | ||
/// about them do throw. | ||
/// @param tokenId The identifier for an ABT | ||
/// @return The address of the owner bound to the ABT | ||
function ownerOf(uint256 tokenId) external view returns (address); | ||
/// @notice Destroys `tokenId`. At any time, an ABT receiver must be able to | ||
/// disassociate themselves from an ABT publicly through calling this | ||
/// function. | ||
/// @dev Must emit a `event Revoke` with the `address to` field pointing to | ||
/// the zero address. | ||
/// @param tokenId The identifier for an ABT | ||
function burn(uint256 tokenId) external; | ||
} | ||
|
||
/// @notice Reference implementation of EIP-4973 tokens. | ||
/// @author TimDaub (https://github.com/rugpullindex/ERC4973/blob/master/src/ERC4973.sol) | ||
abstract contract ERC4973 is ERC165, IERC721Metadata, IERC4973 { | ||
string private _name; | ||
string private _symbol; | ||
|
||
mapping(uint256 => address) private _owners; | ||
mapping(uint256 => string) private _tokenURIs; | ||
mapping(address => uint256) private _balances; | ||
|
||
constructor( | ||
string memory name_, | ||
string memory symbol_ | ||
) { | ||
_name = name_; | ||
_symbol = symbol_; | ||
} | ||
|
||
function supportsInterface(bytes4 interfaceId) public view override returns (bool) { | ||
return | ||
interfaceId == type(IERC721Metadata).interfaceId || | ||
interfaceId == type(IERC4973).interfaceId || | ||
super.supportsInterface(interfaceId); | ||
} | ||
|
||
function name() public view virtual override returns (string memory) { | ||
return _name; | ||
} | ||
|
||
function symbol() public view virtual override returns (string memory) { | ||
return _symbol; | ||
} | ||
|
||
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { | ||
require(_exists(tokenId), "tokenURI: token doesn't exist"); | ||
return _tokenURIs[tokenId]; | ||
} | ||
|
||
function burn(uint256 tokenId) public virtual override { | ||
require(msg.sender == ownerOf(tokenId), "burn: sender must be owner"); | ||
_burn(tokenId); | ||
} | ||
|
||
function balanceOf(address owner) public view virtual override returns (uint256) { | ||
require(owner != address(0), "balanceOf: address zero is not a valid owner"); | ||
return _balances[owner]; | ||
} | ||
|
||
function ownerOf(uint256 tokenId) public view virtual returns (address) { | ||
address owner = _owners[tokenId]; | ||
require(owner != address(0), "ownerOf: token doesn't exist"); | ||
return owner; | ||
} | ||
|
||
function _exists(uint256 tokenId) internal view virtual returns (bool) { | ||
return _owners[tokenId] != address(0); | ||
} | ||
|
||
function _mint( | ||
address to, | ||
uint256 tokenId, | ||
string memory uri | ||
) internal virtual returns (uint256) { | ||
require(!_exists(tokenId), "mint: tokenID exists"); | ||
_balances[to] += 1; | ||
_owners[tokenId] = to; | ||
_tokenURIs[tokenId] = uri; | ||
emit Attest(to, tokenId); | ||
return tokenId; | ||
} | ||
|
||
function _burn(uint256 tokenId) internal virtual { | ||
address owner = ownerOf(tokenId); | ||
|
||
_balances[owner] -= 1; | ||
delete _owners[tokenId]; | ||
delete _tokenURIs[tokenId]; | ||
|
||
emit Revoke(owner, tokenId); | ||
} | ||
} | ||
|
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.