ERC1155 internal workings

How does the minting for ERC1155 work?

:memo:Details

My starting point was from Rarible contract that implements ERC1155Upgradeable.sol (Openzeppelin)
https://github.com/rariblecom/protocol-contracts/blob/master/tokens/contracts/erc-1155/ERC1155Lazy.sol

function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual override {
    uint newMinted = amount.add(minted[id]);
    require(newMinted <= supply[id], "more than supply");
    minted[id] = newMinted;
    super._mint(account, id, amount, data);
}

this calls the _mint function from ERC1155Upgradeable.sol
https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/token/ERC1155/ERC1155Upgradeable.sol

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

    address operator = _msgSender();

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

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

    _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);
}

this functions calls

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

function _doSafeTransferAcceptanceCheck(
    address operator,
    address from,
    address to,
    uint256 id,
    uint256 amount,
    bytes memory data
)
    private
{
    if (to.isContract()) {
        try IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {
            if (response != IERC1155ReceiverUpgradeable(to).onERC1155Received.selector) {
                revert("ERC1155: ERC1155Receiver rejected tokens");
            }
        } catch Error(string memory reason) {
            revert(reason);
        } catch {
            revert("ERC1155: transfer to non ERC1155Receiver implementer");
        }
    }
}

at this point I’m getting lost

what is happing here:

IERC1155ReceiverUpgradeable(to).onERC1155Received(operator, from, id, amount, data)

why is a function selector used?
read that docs but still could not understand it.
(https://docs.soliditylang.org/en/latest/abi-spec.html#abi-function-selector)

where does the minting take place?

also the same question for:

_doSafeBatchTransferAcceptanceCheck

        try IERC1155ReceiverUpgradeable(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (bytes4 response) {

How is contract able to mint a batch of NFTs?

:computer: Environment
“@openzeppelin/contracts-upgradeable”: “^4.0.0”,
“truffle”: “^5.3.1”

:1234: Code to reproduce
openzeppelin/contracts-upgradeable

A similar question I have is even though onERC1155Received or onERC721Received return “bad” values, it does not necessarily mean the receiving address does not support ERC721 sending and receiving functionalities.

The purpose of this function is to protect against sending an ERC721/ERC1155 token to an address such that the token sent will forever lost. But a possibility exists that the receiving address is a semi-ERC721 compliant contract, i…e., it can receive and send ERC721 tokens. It is just not having the onERC721Received function implemented. Would that still be a problem?

Therefore, in my opinion, the function onERC721Received is somewhat incomplete in serving its purpose. Correct?

@Skyge @abcoathup @frangio a short explanation would be super helpful, if you have the time