diff --git a/contracts/token/ERC1155/ERC1155.sol b/contracts/token/ERC1155/ERC1155.sol index 91c98a71486..609cb78ac17 100644 --- a/contracts/token/ERC1155/ERC1155.sol +++ b/contracts/token/ERC1155/ERC1155.sol @@ -31,8 +31,8 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { // Used as the URI for all token types by relying on ID substition, e.g. https://token-cdn-domain/{id}.json string private _uri; - // Mapping token ID to that token being registered as existing - mapping (uint256 => bool) private _tokenExists; + // Mapping token ID to that token being registered as existing (1 for existing, 0 for not existing) + mapping (uint256 => uint256) private _tokenExists; /* * bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e @@ -88,7 +88,6 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { */ function balanceOf(address account, uint256 id) public view override returns (uint256) { require(account != address(0), "ERC1155: balance query for the zero address"); - require(_exists(id), "ERC1155: balance query for nonexistent token"); return _balances[id][account]; } @@ -234,28 +233,29 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { } /** - * @dev Register a token ID so other contract functionality knows this token - * actually exists and this ID is valid. Minting will automatically call this. - * Also emits an event to flag the existence, see the spec: + * @dev Register an `id` so other contract functionality knows this token actually + * exists and this ID is valid. Minting will automatically call this. + * If `sendEvent` is true, emits an event to flag the existence, see the spec: * "To broadcast the existence of a token ID with no initial balance, the contract * SHOULD emit the TransferSingle event from 0x0 to 0x0, with the token creator as * _operator, and a _value of 0." - * @param id uint256 ID of the token to register + * Minting will call this without sending an event as a similar event is sent for + * the minting itself already. */ - function _registerToken(uint256 id) internal virtual { - if (!_tokenExists[id]) { - _tokenExists[id] = true; - emit TransferSingle(msg.sender, address(0), address(0), id, 0); + function _registerToken(uint256 id, bool sendEvent) internal virtual { + if (_tokenExists[id] == 0) { + _tokenExists[id] = 1; + if (sendEvent) { + emit TransferSingle(msg.sender, address(0), address(0), id, 0); + } } } /** - * @dev Returns whether the specified token exists. Use {_registerTokenID} to set this flag. - * @param id uint256 ID of the token to query the existence of - * @return bool whether the token exists + * @dev Returns whether the token `id` exists. Use {_registerToken} to set this flag. */ function _exists(uint256 id) internal view returns (bool) { - return _tokenExists[id]; + return _tokenExists[id] != 0; } /** @@ -277,8 +277,9 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data); if (!_exists(id)) { - _registerToken(id); + _registerToken(id, false); } + _balances[id][account] = _balances[id][account].add(amount); emit TransferSingle(operator, address(0), account, id, amount); @@ -304,7 +305,7 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { for (uint i = 0; i < ids.length; i++) { if (!_exists(ids[i])) { - _registerToken(ids[i]); + _registerToken(ids[i], false); } _balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]); }