@@ -24,6 +24,9 @@ contract ERC1155 is ERC165, IERC1155
24
24
// Mapping from account to operator approvals
25
25
mapping (address => mapping (address => bool )) private _operatorApprovals;
26
26
27
+ // Mapping token ID to that token being registered as existing
28
+ mapping (uint256 => bool ) private _tokenExists;
29
+
27
30
/*
28
31
* bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
29
32
* bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
@@ -53,6 +56,7 @@ contract ERC1155 is ERC165, IERC1155
53
56
*/
54
57
function balanceOf (address account , uint256 id ) public view override returns (uint256 ) {
55
58
require (account != address (0 ), "ERC1155: balance query for the zero address " );
59
+ require (_exists (id), "ERC1155: balance query for nonexistent token " );
56
60
return _balances[id][account];
57
61
}
58
62
@@ -80,6 +84,7 @@ contract ERC1155 is ERC165, IERC1155
80
84
81
85
for (uint256 i = 0 ; i < accounts.length ; ++ i) {
82
86
require (accounts[i] != address (0 ), "ERC1155: some address in batch balance query is zero " );
87
+ require (_exists (ids[i]), "ERC1155: some token in batch balance query does not exist " );
83
88
batchBalances[i] = _balances[ids[i]][accounts[i]];
84
89
}
85
90
@@ -194,14 +199,21 @@ contract ERC1155 is ERC165, IERC1155
194
199
}
195
200
196
201
/**
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
+ _tokenExists[id] = true ;
208
+ }
209
+
210
+ /**
211
+ * @dev Returns whether the specified token exists. Use {_registerTokenID} to set this flag.
200
212
* @param id uint256 ID of the token to query the existence of
201
213
* @return bool whether the token exists
202
214
*/
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] ;
205
217
}
206
218
207
219
/**
@@ -214,6 +226,9 @@ contract ERC1155 is ERC165, IERC1155
214
226
function _mint (address to , uint256 id , uint256 value , bytes memory data ) internal virtual {
215
227
require (to != address (0 ), "ERC1155: mint to the zero address " );
216
228
229
+ if (! _exists (id)) {
230
+ _registerToken (id);
231
+ }
217
232
_balances[id][to] = _balances[id][to].add (value);
218
233
emit TransferSingle (msg .sender , address (0 ), to, id, value);
219
234
@@ -232,6 +247,9 @@ contract ERC1155 is ERC165, IERC1155
232
247
require (ids.length == values.length , "ERC1155: minted IDs and values must have same lengths " );
233
248
234
249
for (uint i = 0 ; i < ids.length ; i++ ) {
250
+ if (! _exists (ids[i])) {
251
+ _registerToken (ids[i]);
252
+ }
235
253
_balances[ids[i]][to] = values[i].add (_balances[ids[i]][to]);
236
254
}
237
255
0 commit comments