eRon Blockchain Documentation

eRon Blockchain holds various contracts standards, which you can find below.

ERC-20 Token Standards, Extensions and utils

There are a few core contracts that implement the behavior specified in the ERC20 token standard:

{IERC20}: the interface all ERC-20 implementations should conform to.

{IERC20Metadata}: the extended ERC-20 interface including the name, symbol and decimals functions.

{ERC20}: the implementation of the ERC-20 interface, including the name, symbol and decimals optional standard extension to the base interface.

Additionally there are multiple custom extensions, including:

{ERC20Permit}: gasless approval of tokens (standardized as ERC-2612).

{ERC20Burnable}: destruction of own tokens.

{ERC20Capped}: enforcement of a cap to the total supply when minting tokens.

{ERC20Pausable}: ability to pause token transfers.

{ERC20FlashMint}: token level support for flash loans through the minting and burning of ephemeral tokens (standardized as ERC-3156).

{ERC20Votes}: support for voting and vote delegation.

{ERC20Wrapper}: wrapper to create an ERC-20 backed by another ERC-20, with deposit and withdraw methods. Useful in conjunction with {ERC20Votes}.

{ERC1363}: support for calling the target of a transfer or approval, enabling code execution on the receiver within a single transaction.

{ERC4626}: tokenized vault that manages shares (represented as ERC-20) that are backed by assets (another ERC-20).

Finally, there are some utilities to interact with ERC-20 contracts in various ways:

{SafeERC20}: a wrapper around the interface that eliminates the need to handle boolean return values.

Other utilities that support ERC-20 assets can be found in codebase:

ERC-20 tokens can be timelocked (held tokens for a beneficiary until a specified time) or vested (released following a given schedule) using a {VestingWallet}.

ERC-20

                                    // SPDX-License-Identifier: MIT
                                    
                                    pragma solidity ^0.8.20;
                                    
                                    import {IERC20} from "./IERC20.sol";
                                    import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
                                    import {Context} from "../../utils/Context.sol";
                                    import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

                                    abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
                                        mapping(address account => uint256) private _balances;
                                    
                                        mapping(address account => mapping(address spender => uint256)) private _allowances;
                                    
                                        uint256 private _totalSupply;
                                    
                                        string private _name;
                                        string private _symbol;

                                        constructor(string memory name_, string memory symbol_) {
                                            _name = name_;
                                            _symbol = symbol_;
                                        }

                                        function name() public view virtual returns (string memory) {
                                            return _name;
                                        }

                                        function symbol() public view virtual returns (string memory) {
                                            return _symbol;
                                        }

                                        function decimals() public view virtual returns (uint8) {
                                            return 18;
                                        }

                                        function totalSupply() public view virtual returns (uint256) {
                                            return _totalSupply;
                                        }

                                        function balanceOf(address account) public view virtual returns (uint256) {
                                            return _balances[account];
                                        }

                                        function transfer(address to, uint256 value) public virtual returns (bool) {
                                            address owner = _msgSender();
                                            _transfer(owner, to, value);
                                            return true;
                                        }

                                        function allowance(address owner, address spender) public view virtual returns (uint256) {
                                            return _allowances[owner][spender];
                                        }

                                        function approve(address spender, uint256 value) public virtual returns (bool) {
                                            address owner = _msgSender();
                                            _approve(owner, spender, value);
                                            return true;
                                        }

                                        function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
                                            address spender = _msgSender();
                                            _spendAllowance(from, spender, value);
                                            _transfer(from, to, value);
                                            return true;
                                        }
                                    
                                        function _transfer(address from, address to, uint256 value) internal {
                                            if (from == address(0)) {
                                                revert ERC20InvalidSender(address(0));
                                            }
                                            if (to == address(0)) {
                                                revert ERC20InvalidReceiver(address(0));
                                            }
                                            _update(from, to, value);
                                        }

                                        function _update(address from, address to, uint256 value) internal virtual {
                                            if (from == address(0)) {
                                                _totalSupply += value;
                                            } else {
                                                uint256 fromBalance = _balances[from];
                                                if (fromBalance < value) {
                                                    revert ERC20InsufficientBalance(from, fromBalance, value);
                                                }
                                                unchecked {
                                                    // Overflow not possible: value <= fromBalance <= totalSupply.
                                                    _balances[from] = fromBalance - value;
                                                }
                                            }
                                    
                                            if (to == address(0)) {
                                                unchecked {
                                                    _totalSupply -= value;
                                                }
                                            } else {
                                                unchecked {
                                                    _balances[to] += value;
                                                }
                                            }
                                    
                                            emit Transfer(from, to, value);
                                        }

                                        function _mint(address account, uint256 value) internal {
                                            if (account == address(0)) {
                                                revert ERC20InvalidReceiver(address(0));
                                            }
                                            _update(address(0), account, value);
                                        }

                                        function _burn(address account, uint256 value) internal {
                                            if (account == address(0)) {
                                                revert ERC20InvalidSender(address(0));
                                            }
                                            _update(account, address(0), value);
                                        }

                                        function _approve(address owner, address spender, uint256 value) internal {
                                            _approve(owner, spender, value, true);
                                        }

                                        function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
                                            if (owner == address(0)) {
                                                revert ERC20InvalidApprover(address(0));
                                            }
                                            if (spender == address(0)) {
                                                revert ERC20InvalidSpender(address(0));
                                            }
                                            _allowances[owner][spender] = value;
                                            if (emitEvent) {
                                                emit Approval(owner, spender, value);
                                            }
                                        }

                                        function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
                                            uint256 currentAllowance = allowance(owner, spender);
                                            if (currentAllowance != type(uint256).max) {
                                                if (currentAllowance < value) {
                                                    revert ERC20InsufficientAllowance(spender, currentAllowance, value);
                                                }
                                                unchecked {
                                                    _approve(owner, spender, currentAllowance - value, false);
                                                }
                                            }
                                        }
                                    }
                                

ERC-721 Token Standards, Extensions and utils

This set of interfaces, contracts, and utilities are all related to the ERC-721 Non-Fungible Token Standard.

The ERC specifies four interfaces:

{IERC721}: Core functionality required in all compliant implementation.

{IERC721Metadata}: Optional extension that adds name, symbol, and token URI, almost always included.

{IERC721Enumerable}: Optional extension that allows enumerating the tokens on chain, often not included since it requires large gas overhead.

{IERC721Receiver}: An interface that must be implemented by contracts if they want to accept tokens through safeTransferFrom.

{ERC721}: The core and metadata extensions, with a base URI mechanism.

{ERC721Enumerable}: The enumerable extension.

{ERC721Holder}: A bare bones implementation of the receiver interface.

Additionally there are a few of other extensions:

{ERC721Consecutive}: An implementation of ERC-2309 for minting batchs of tokens during construction, in accordance with ERC-721.

{ERC721URIStorage}: A more flexible but more expensive way of storing metadata.

{ERC721Votes}: Support for voting and vote delegation.

{ERC721Royalty}: A way to signal royalty information following ERC-2981.

{ERC721Pausable}: A primitive to pause contract operation.

{ERC721Burnable}: A way for token holders to burn their own tokens.

{ERC721Wrapper}: Wrapper to create an ERC-721 backed by another ERC-721, with deposit and withdraw methods. Useful in conjunction with {ERC721Votes}.

ERC-721

                                    // SPDX-License-Identifier: MIT
                                    
                                    pragma solidity ^0.8.20;
                                    
                                    import {IERC721} from "./IERC721.sol";
                                    import {IERC721Metadata} from "./extensions/IERC721Metadata.sol";
                                    import {ERC721Utils} from "./utils/ERC721Utils.sol";
                                    import {Context} from "../../utils/Context.sol";
                                    import {Strings} from "../../utils/Strings.sol";
                                    import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
                                    import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol";

                                    abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors {
                                        using Strings for uint256;
                                    
                                        string private _name;
                                    
                                        string private _symbol;
                                    
                                        mapping(uint256 tokenId => address) private _owners;
                                    
                                        mapping(address owner => uint256) private _balances;
                                    
                                        mapping(uint256 tokenId => address) private _tokenApprovals;
                                    
                                        mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;

                                        constructor(string memory name_, string memory symbol_) {
                                            _name = name_;
                                            _symbol = symbol_;
                                        }

                                        function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
                                            return
                                                interfaceId == type(IERC721).interfaceId ||
                                                interfaceId == type(IERC721Metadata).interfaceId ||
                                                super.supportsInterface(interfaceId);
                                        }

                                        function balanceOf(address owner) public view virtual returns (uint256) {
                                            if (owner == address(0)) {
                                                revert ERC721InvalidOwner(address(0));
                                            }
                                            return _balances[owner];
                                        }

                                        function ownerOf(uint256 tokenId) public view virtual returns (address) {
                                            return _requireOwned(tokenId);
                                        }

                                        function name() public view virtual returns (string memory) {
                                            return _name;
                                        }

                                        function symbol() public view virtual returns (string memory) {
                                            return _symbol;
                                        }

                                        function tokenURI(uint256 tokenId) public view virtual returns (string memory) {
                                            _requireOwned(tokenId);
                                    
                                            string memory baseURI = _baseURI();
                                            return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : "";
                                        }

                                        function _baseURI() internal view virtual returns (string memory) {
                                            return "";
                                        }
                                    
                                        function approve(address to, uint256 tokenId) public virtual {
                                            _approve(to, tokenId, _msgSender());
                                        }

                                        function getApproved(uint256 tokenId) public view virtual returns (address) {
                                            _requireOwned(tokenId);
                                    
                                            return _getApproved(tokenId);
                                        }

                                        function setApprovalForAll(address operator, bool approved) public virtual {
                                            _setApprovalForAll(_msgSender(), operator, approved);
                                        }

                                        function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {
                                            return _operatorApprovals[owner][operator];
                                        }

                                        function transferFrom(address from, address to, uint256 tokenId) public virtual {
                                            if (to == address(0)) {
                                                revert ERC721InvalidReceiver(address(0));
                                            }
                                            address previousOwner = _update(to, tokenId, _msgSender());
                                            if (previousOwner != from) {
                                                revert ERC721IncorrectOwner(from, tokenId, previousOwner);
                                            }
                                        }

                                        function safeTransferFrom(address from, address to, uint256 tokenId) public {
                                            safeTransferFrom(from, to, tokenId, "");
                                        }

                                        function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {
                                            transferFrom(from, to, tokenId);
                                            ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
                                        }

                                        function _ownerOf(uint256 tokenId) internal view virtual returns (address) {
                                            return _owners[tokenId];
                                        }
                                    
                                        function _getApproved(uint256 tokenId) internal view virtual returns (address) {
                                            return _tokenApprovals[tokenId];
                                        }

                                        function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {
                                            return
                                                spender != address(0) &&
                                                (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
                                        }
                                    
                                        function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {
                                            if (!_isAuthorized(owner, spender, tokenId)) {
                                                if (owner == address(0)) {
                                                    revert ERC721NonexistentToken(tokenId);
                                                } else {
                                                    revert ERC721InsufficientApproval(spender, tokenId);
                                                }
                                            }
                                        }
                                    
                                        function _increaseBalance(address account, uint128 value) internal virtual {
                                            unchecked {
                                                _balances[account] += value;
                                            }
                                        }
                                    
                                        function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {
                                            address from = _ownerOf(tokenId);
                                    
                                            // Perform (optional) operator check
                                            if (auth != address(0)) {
                                                _checkAuthorized(from, auth, tokenId);
                                            }
                                    
                                            if (from != address(0)) {
                                                // Clear approval. No need to re-authorize or emit the Approval event
                                                _approve(address(0), tokenId, address(0), false);
                                    
                                                unchecked {
                                                    _balances[from] -= 1;
                                                }
                                            }
                                    
                                            if (to != address(0)) {
                                                unchecked {
                                                    _balances[to] += 1;
                                                }
                                            }
                                    
                                            _owners[tokenId] = to;
                                    
                                            emit Transfer(from, to, tokenId);
                                    
                                            return from;
                                        }

                                        function _mint(address to, uint256 tokenId) internal {
                                            if (to == address(0)) {
                                                revert ERC721InvalidReceiver(address(0));
                                            }
                                            address previousOwner = _update(to, tokenId, address(0));
                                            if (previousOwner != address(0)) {
                                                revert ERC721InvalidSender(address(0));
                                            }
                                        }

                                        function _safeMint(address to, uint256 tokenId) internal {
                                            _safeMint(to, tokenId, "");
                                        }

                                        function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {
                                            _mint(to, tokenId);
                                            ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);
                                        }

                                        function _burn(uint256 tokenId) internal {
                                            address previousOwner = _update(address(0), tokenId, address(0));
                                            if (previousOwner == address(0)) {
                                                revert ERC721NonexistentToken(tokenId);
                                            }
                                        }

                                        function _transfer(address from, address to, uint256 tokenId) internal {
                                            if (to == address(0)) {
                                                revert ERC721InvalidReceiver(address(0));
                                            }
                                            address previousOwner = _update(to, tokenId, address(0));
                                            if (previousOwner == address(0)) {
                                                revert ERC721NonexistentToken(tokenId);
                                            } else if (previousOwner != from) {
                                                revert ERC721IncorrectOwner(from, tokenId, previousOwner);
                                            }
                                        }

                                        function _safeTransfer(address from, address to, uint256 tokenId) internal {
                                            _safeTransfer(from, to, tokenId, "");
                                        }

                                        function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
                                            _transfer(from, to, tokenId);
                                            ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);
                                        }

                                        function _approve(address to, uint256 tokenId, address auth) internal {
                                            _approve(to, tokenId, auth, true);
                                        }

                                        function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual {
                                            // Avoid reading the owner unless necessary
                                            if (emitEvent || auth != address(0)) {
                                                address owner = _requireOwned(tokenId);
                                    
                                                if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) {
                                                    revert ERC721InvalidApprover(auth);
                                                }
                                    
                                                if (emitEvent) {
                                                    emit Approval(owner, to, tokenId);
                                                }
                                            }
                                    
                                            _tokenApprovals[tokenId] = to;
                                        }

                                        function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
                                            if (operator == address(0)) {
                                                revert ERC721InvalidOperator(operator);
                                            }
                                            _operatorApprovals[owner][operator] = approved;
                                            emit ApprovalForAll(owner, operator, approved);
                                        }

                                        function _requireOwned(uint256 tokenId) internal view returns (address) {
                                            address owner = _ownerOf(tokenId);
                                            if (owner == address(0)) {
                                                revert ERC721NonexistentToken(tokenId);
                                            }
                                            return owner;
                                        }
                                    }
                                

ERC-1155 Token Standards, Extensions and utils

This set of interfaces and contracts are all related to the ERC-1155 Multi Token Standard.

The ERC consists of three interfaces which fulfill different roles:

{IERC1155} is the mandatory interface.

{IERC1155MetadataURI} is the optional extension.

{IERC1155Receiver} that must be implemented by smart contracts in order to receive ERC-1155 token transfers

Additionally there are multiple custom extensions, including:

({ERC1155Pausable}) for designation of addresses that can pause token transfers for all users.

({ERC1155Burnable}) for destruction of own tokens.

{{ERC1155Supply}} that adds tracking of total supply per id.

{{ERC1155URIStorage}}

{{ERC1155Holder}} that will allow a contract to hold ERC-1155 tokens.

ERC-1155

                                    // SPDX-License-Identifier: MIT
                                    
                                    pragma solidity ^0.8.20;
                                    
                                    import {IERC1155} from "./IERC1155.sol";
                                    import {IERC1155MetadataURI} from "./extensions/IERC1155MetadataURI.sol";
                                    import {ERC1155Utils} from "./utils/ERC1155Utils.sol";
                                    import {Context} from "../../utils/Context.sol";
                                    import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
                                    import {Arrays} from "../../utils/Arrays.sol";
                                    import {IERC1155Errors} from "../../interfaces/draft-IERC6093.sol";
                                    
                                    abstract contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI, IERC1155Errors {
                                        using Arrays for uint256[];
                                        using Arrays for address[];
                                    
                                        mapping(uint256 id => mapping(address account => uint256)) private _balances;
                                    
                                        mapping(address account => mapping(address operator => bool)) private _operatorApprovals;
                                    
                                        string private _uri;

                                        constructor(string memory uri_) {
                                            _setURI(uri_);
                                        }

                                        function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
                                            return
                                                interfaceId == type(IERC1155).interfaceId ||
                                                interfaceId == type(IERC1155MetadataURI).interfaceId ||
                                                super.supportsInterface(interfaceId);
                                        }

                                        function uri(uint256 /* id */) public view virtual returns (string memory) {
                                            return _uri;
                                        }

                                        function balanceOf(address account, uint256 id) public view virtual returns (uint256) {
                                            return _balances[id][account];
                                        }

                                        function balanceOfBatch(
                                            address[] memory accounts,
                                            uint256[] memory ids
                                        ) public view virtual returns (uint256[] memory) {
                                            if (accounts.length != ids.length) {
                                                revert ERC1155InvalidArrayLength(ids.length, accounts.length);
                                            }
                                    
                                            uint256[] memory batchBalances = new uint256[](accounts.length);
                                    
                                            for (uint256 i = 0; i < accounts.length; ++i) {
                                                batchBalances[i] = balanceOf(accounts.unsafeMemoryAccess(i), ids.unsafeMemoryAccess(i));
                                            }
                                    
                                            return batchBalances;
                                        }

                                        function setApprovalForAll(address operator, bool approved) public virtual {
                                            _setApprovalForAll(_msgSender(), operator, approved);
                                        }

                                        function isApprovedForAll(address account, address operator) public view virtual returns (bool) {
                                            return _operatorApprovals[account][operator];
                                        }

                                        function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {
                                            address sender = _msgSender();
                                            if (from != sender && !isApprovedForAll(from, sender)) {
                                                revert ERC1155MissingApprovalForAll(sender, from);
                                            }
                                            _safeTransferFrom(from, to, id, value, data);
                                        }

                                        function safeBatchTransferFrom(
                                            address from,
                                            address to,
                                            uint256[] memory ids,
                                            uint256[] memory values,
                                            bytes memory data
                                        ) public virtual {
                                            address sender = _msgSender();
                                            if (from != sender && !isApprovedForAll(from, sender)) {
                                                revert ERC1155MissingApprovalForAll(sender, from);
                                            }
                                            _safeBatchTransferFrom(from, to, ids, values, data);
                                        }

                                        function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {
                                            if (ids.length != values.length) {
                                                revert ERC1155InvalidArrayLength(ids.length, values.length);
                                            }
                                    
                                            address operator = _msgSender();
                                    
                                            for (uint256 i = 0; i < ids.length; ++i) {
                                                uint256 id = ids.unsafeMemoryAccess(i);
                                                uint256 value = values.unsafeMemoryAccess(i);
                                    
                                                if (from != address(0)) {
                                                    uint256 fromBalance = _balances[id][from];
                                                    if (fromBalance < value) {
                                                        revert ERC1155InsufficientBalance(from, fromBalance, value, id);
                                                    }
                                                    unchecked {
                                                        // Overflow not possible: value <= fromBalance
                                                        _balances[id][from] = fromBalance - value;
                                                    }
                                                }
                                    
                                                if (to != address(0)) {
                                                    _balances[id][to] += value;
                                                }
                                            }
                                    
                                            if (ids.length == 1) {
                                                uint256 id = ids.unsafeMemoryAccess(0);
                                                uint256 value = values.unsafeMemoryAccess(0);
                                                emit TransferSingle(operator, from, to, id, value);
                                            } else {
                                                emit TransferBatch(operator, from, to, ids, values);
                                            }
                                        }

                                        function _updateWithAcceptanceCheck(
                                            address from,
                                            address to,
                                            uint256[] memory ids,
                                            uint256[] memory values,
                                            bytes memory data
                                        ) internal virtual {
                                            _update(from, to, ids, values);
                                            if (to != address(0)) {
                                                address operator = _msgSender();
                                                if (ids.length == 1) {
                                                    uint256 id = ids.unsafeMemoryAccess(0);
                                                    uint256 value = values.unsafeMemoryAccess(0);
                                                    ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);
                                                } else {
                                                    ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data);
                                                }
                                            }
                                        }

                                        function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {
                                            if (to == address(0)) {
                                                revert ERC1155InvalidReceiver(address(0));
                                            }
                                            if (from == address(0)) {
                                                revert ERC1155InvalidSender(address(0));
                                            }
                                            (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
                                            _updateWithAcceptanceCheck(from, to, ids, values, data);
                                        }

                                        function _safeBatchTransferFrom(
                                            address from,
                                            address to,
                                            uint256[] memory ids,
                                            uint256[] memory values,
                                            bytes memory data
                                        ) internal {
                                            if (to == address(0)) {
                                                revert ERC1155InvalidReceiver(address(0));
                                            }
                                            if (from == address(0)) {
                                                revert ERC1155InvalidSender(address(0));
                                            }
                                            _updateWithAcceptanceCheck(from, to, ids, values, data);
                                        }

                                        function _setURI(string memory newuri) internal virtual {
                                            _uri = newuri;
                                        }
                                    
                                        function _mint(address to, uint256 id, uint256 value, bytes memory data) internal {
                                            if (to == address(0)) {
                                                revert ERC1155InvalidReceiver(address(0));
                                            }
                                            (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
                                            _updateWithAcceptanceCheck(address(0), to, ids, values, data);
                                        }
 
                                        function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {
                                            if (to == address(0)) {
                                                revert ERC1155InvalidReceiver(address(0));
                                            }
                                            _updateWithAcceptanceCheck(address(0), to, ids, values, data);
                                        }

                                        function _burn(address from, uint256 id, uint256 value) internal {
                                            if (from == address(0)) {
                                                revert ERC1155InvalidSender(address(0));
                                            }
                                            (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);
                                            _updateWithAcceptanceCheck(from, address(0), ids, values, "");
                                        }

                                        function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {
                                            if (from == address(0)) {
                                                revert ERC1155InvalidSender(address(0));
                                            }
                                            _updateWithAcceptanceCheck(from, address(0), ids, values, "");
                                        }

                                        function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {
                                            if (operator == address(0)) {
                                                revert ERC1155InvalidOperator(address(0));
                                            }
                                            _operatorApprovals[owner][operator] = approved;
                                            emit ApprovalForAll(owner, operator, approved);
                                        }

                                        function _asSingletonArrays(
                                            uint256 element1,
                                            uint256 element2
                                        ) private pure returns (uint256[] memory array1, uint256[] memory array2) {
                                            assembly {
                                                array1 := mload(0x40)
                                                mstore(array1, 1)
                                                mstore(add(array1, 0x20), element1)
                                    
                                                array2 := add(array1, 0x40)
                                                mstore(array2, 1)
                                                mstore(add(array2, 0x20), element2)
                                    
                                                mstore(0x40, add(array2, 0x40))
                                            }
                                        }
                                    }