1

I'm new to Solidity and smart contracts, and was playing around with the ERC1155 contract from OpenZeppelin.

I was wondering how (from a technical perspective) you are able to _mint a token to address B when authenticated with address A, but you are not able to _burn a token from address B when authenticated with address A.

I mean, I get it that it's not allowed, otherwise you can start burning other people's tokens, but I couldn't see the technical reason for that in the contract. As far as I can see, _mint and _burn look very similar:

function _mint(
    address to,
    uint256 id,
    uint256 amount,
    bytes memory data
) internal virtual {
    require(to != address(0), "ERC1155: mint to the zero address");

    address operator = _msgSender();
    uint256[] memory ids = _asSingletonArray(id);
    uint256[] memory amounts = _asSingletonArray(amount);

    _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);

    _balances[id][to] += amount;
    emit TransferSingle(operator, address(0), to, id, amount);

    _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data);

    _afterTokenTransfer(operator, address(0), to, ids, amounts, data);
}

function _burn(
    address from,
    uint256 id,
    uint256 amount
) internal virtual {
    require(from != address(0), "ERC1155: burn from the zero address");

    address operator = _msgSender();
    uint256[] memory ids = _asSingletonArray(id);
    uint256[] memory amounts = _asSingletonArray(amount);

    _beforeTokenTransfer(operator, from, address(0), ids, amounts, "");

    uint256 fromBalance = _balances[id][from];
    require(fromBalance >= amount, "ERC1155: burn amount exceeds balance");
    unchecked {
        _balances[id][from] = fromBalance - amount;
    }

    emit TransferSingle(operator, from, address(0), id, amount);

    _afterTokenTransfer(operator, from, address(0), ids, amounts, "");
}

So what is it exactly that makes the transaction fail if you try to burn someone else's tokens? Or is that just "by definition" because that's how the blockchain works, or something like that?

1 Answer 1

1

_mint and _burn are only internal functions, therefore end users can't call them directly.

Upon these functions you need to create your own public/external functions which will implement the restrictions you want to make.

So for example your burn function's signature can be function burn(uint256 id, uint256 amount) external, and it will just call _burn(msg.sender, id, amount), and therefore if the sender does not have this amount of ID tokens, the tx will revert because of require(fromBalance >= amount, "ERC1155: burn amount exceeds balance").

1
  • Right! God, I feel stupid, I indeed have this particular line in my own burn function in my contract: require(msg.sender == account); _burn(account, id, amount);
    – binoculars
    Commented Feb 18, 2022 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.