Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce an ERC-1155 _exists() function #2185

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions contracts/token/ERC1155/ERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ 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 (1 for existing, 0 for not existing)
mapping (uint256 => uint256) private _tokenExists;
Copy link
Contributor

@frangio frangio Aug 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this uint256 => uint256 instead of uint256 => bool?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's because of #2185 (comment) - do you think that's a bad idea?


/*
* bytes4(keccak256('balanceOf(address,uint256)')) == 0x00fdd58e
* bytes4(keccak256('balanceOfBatch(address[],uint256[])')) == 0x4e1273f4
Expand Down Expand Up @@ -229,6 +232,32 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
_uri = newuri;
}

/**
* @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."
* Minting will call this without sending an event as a similar event is sent for
* the minting itself already.
*/
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 token `id` exists. Use {_registerToken} to set this flag.
*/
function _exists(uint256 id) internal view returns (bool) {
return _tokenExists[id] != 0;
}

/**
* @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.
*
Expand All @@ -247,6 +276,10 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {

_beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);

if (!_exists(id)) {
_registerToken(id, false);
}

_balances[id][account] = _balances[id][account].add(amount);
emit TransferSingle(operator, address(0), account, id, amount);

Expand All @@ -271,6 +304,9 @@ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {
_beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

for (uint i = 0; i < ids.length; i++) {
if (!_exists(ids[i])) {
_registerToken(ids[i], false);
}
_balances[ids[i]][to] = amounts[i].add(_balances[ids[i]][to]);
}

Expand Down