Skip to content

Commit 9af78df

Browse files
committed
Use an explicit registration internally to mark token IDs as existing
1 parent 1a921e7 commit 9af78df

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

contracts/token/ERC1155/ERC1155.sol

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ contract ERC1155 is ERC165, IERC1155
2424
// Mapping from account to operator approvals
2525
mapping (address => mapping(address => bool)) private _operatorApprovals;
2626

27+
// Mapping token ID to that token being registered as existing
28+
mapping (uint256 => bool) private _tokenExists;
29+
2730
/*
2831
* bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
2932
* bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
@@ -53,6 +56,7 @@ contract ERC1155 is ERC165, IERC1155
5356
*/
5457
function balanceOf(address account, uint256 id) public view override returns (uint256) {
5558
require(account != address(0), "ERC1155: balance query for the zero address");
59+
require(_exists(id), "ERC1155: balance query for nonexistent token");
5660
return _balances[id][account];
5761
}
5862

@@ -80,6 +84,7 @@ contract ERC1155 is ERC165, IERC1155
8084

8185
for (uint256 i = 0; i < accounts.length; ++i) {
8286
require(accounts[i] != address(0), "ERC1155: some address in batch balance query is zero");
87+
require(_exists(id), "ERC1155: some token in batch balance query does not exist");
8388
batchBalances[i] = _balances[ids[i]][accounts[i]];
8489
}
8590

@@ -194,14 +199,21 @@ contract ERC1155 is ERC165, IERC1155
194199
}
195200

196201
/**
197-
* @dev Returns whether the specified token exists. This is intentionally marked
198-
* `virtual` as specific implementations may want to override to actually have
199-
* existence be respected while the generic implementation always returns true.
202+
* @dev Register a token ID so other contract functionality knows this token
203+
* actually exists and this ID is valid. Minting will automatically call this.
204+
* @param id uint256 ID of the token to register
205+
*/
206+
function _registerToken(uint256 id) internal virtual {
207+
return _tokenExists[id] = true;
208+
}
209+
210+
/**
211+
* @dev Returns whether the specified token exists. Use {_registerTokenID} to set this flag.
200212
* @param id uint256 ID of the token to query the existence of
201213
* @return bool whether the token exists
202214
*/
203-
function _exists(uint256 id) internal view virtual returns (bool) {
204-
return true;
215+
function _exists(uint256 id) internal view returns (bool) {
216+
return _tokenExists[id];
205217
}
206218

207219
/**
@@ -214,6 +226,9 @@ contract ERC1155 is ERC165, IERC1155
214226
function _mint(address to, uint256 id, uint256 value, bytes memory data) internal virtual {
215227
require(to != address(0), "ERC1155: mint to the zero address");
216228

229+
if (!_exists(id)) {
230+
_registerToken(id);
231+
}
217232
_balances[id][to] = _balances[id][to].add(value);
218233
emit TransferSingle(msg.sender, address(0), to, id, value);
219234

@@ -232,6 +247,9 @@ contract ERC1155 is ERC165, IERC1155
232247
require(ids.length == values.length, "ERC1155: minted IDs and values must have same lengths");
233248

234249
for(uint i = 0; i < ids.length; i++) {
250+
if (!_exists(id)) {
251+
_registerToken(id);
252+
}
235253
_balances[ids[i]][to] = values[i].add(_balances[ids[i]][to]);
236254
}
237255

0 commit comments

Comments
 (0)