Closed ghost closed 2 years ago
@noel-yoo On second thought, IsTokenNotFound token_id;
might be actually checking whether a token exists or not. If exists, don't mint a minted token and throw an exception. i.e don't overwrite a minted token
@noel-yoo On second thought,
IsTokenNotFound token_id;
might be actually checking whether a token exists or not. If exists, don't mint a minted token and throw an exception.
Yes, IsTokenNotFound token_id
is valid only if it's possible to throw the CodeTokenExists
.
Can you explain when that is possible?
The new token id can never conflict with another token id because
token_id_count
is increased by 1 each timetoken_id_count
is mutated only by the Minting()
procedureCALL_CONTRACT_FAILED
(i.e MAX-1
-> MAX
-> 0
-> 1
-> 2
is not possible) Burn()
doesn't mutate the the field token_id_count
If the above is correct then IsTokenNotFound token_id;
will never throw the CodeTokenExists
error because the following part never runs:
| True =>
err = CodeTokenExists;
ThrowError err
If unnecessary validations are allowed
Therefore, if some validation is unnecessary, then we should consider removing it.
Although the validation is unnecessary and cannot be tested, still we have a strong reason to keep it then we can comment that why the code is unnecessary and what is the strong reason to keep it.
I was thinking that that check could be a constraint. More for safety purposes.
While the reference contract has no issue, if any future developer is modifying the reference code and calling the procedure from other transitions carelessly, it might be dangerous.
With this constraint, it is guaranteed that this procedure cannot double mint regardless of who is calling the procedure.
I went to check the solidity code too also.
function _mint(
address _to,
uint256 _tokenId
)
internal
virtual
{
require(_to != address(0), ZERO_ADDRESS);
require(idToOwner[_tokenId] == address(0), NFT_ALREADY_EXISTS);
_addNFToken(_to, _tokenId);
emit Transfer(address(0), _to, _tokenId);
}
In the _mint()
case, the validation makes more sense since it's not clear what _tokenId
param will be.
In the Minting() case, the new token ID is quite clear because we have all context.
https://github.com/Zilliqa/ZRC/blob/master/reference/nonfungible-token.scilla#L374-L380
Because of the above logic,
IsTokenNotFound()
will never throw an error. Even with the overflow case, there will be theCALL_CONTRACT_FAILED
error withCannot apply built-in Uint.add: an overflow/underflow occurred to a list of arguments
message.Also,
IsTokenNotFound
is only used for above.Therefore, we can remove
IsTokenNotFound()
and simplify the logic inMinting()
.