123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990 |
- // SPDX-License-Identifier: MIT
- // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC1155/extensions/ERC1155Supply.sol)
- pragma solidity ^0.8.20;
- import {ERC1155} from "../ERC1155.sol";
- import {Arrays} from "../../../utils/Arrays.sol";
- /**
- * @dev Extension of ERC-1155 that adds tracking of total supply per id.
- *
- * Useful for scenarios where Fungible and Non-fungible tokens have to be
- * clearly identified. Note: While a totalSupply of 1 might mean the
- * corresponding is an NFT, there is no guarantees that no other token with the
- * same id are not going to be minted.
- *
- * NOTE: This contract implies a global limit of 2**256 - 1 to the number of tokens
- * that can be minted.
- *
- * CAUTION: This extension should not be added in an upgrade to an already deployed contract.
- */
- abstract contract ERC1155Supply is ERC1155 {
- using Arrays for uint256[];
- mapping(uint256 id => uint256) private _totalSupply;
- uint256 private _totalSupplyAll;
- /**
- * @dev Total value of tokens in with a given id.
- */
- function totalSupply(uint256 id) public view virtual returns (uint256) {
- return _totalSupply[id];
- }
- /**
- * @dev Total value of tokens.
- */
- function totalSupply() public view virtual returns (uint256) {
- return _totalSupplyAll;
- }
- /**
- * @dev Indicates whether any token exist with a given id, or not.
- */
- function exists(uint256 id) public view virtual returns (bool) {
- return totalSupply(id) > 0;
- }
- /**
- * @dev See {ERC1155-_update}.
- */
- function _update(
- address from,
- address to,
- uint256[] memory ids,
- uint256[] memory values
- ) internal virtual override {
- super._update(from, to, ids, values);
- if (from == address(0)) {
- uint256 totalMintValue = 0;
- for (uint256 i = 0; i < ids.length; ++i) {
- uint256 value = values.unsafeMemoryAccess(i);
- // Overflow check required: The rest of the code assumes that totalSupply never overflows
- _totalSupply[ids.unsafeMemoryAccess(i)] += value;
- totalMintValue += value;
- }
- // Overflow check required: The rest of the code assumes that totalSupplyAll never overflows
- _totalSupplyAll += totalMintValue;
- }
- if (to == address(0)) {
- uint256 totalBurnValue = 0;
- for (uint256 i = 0; i < ids.length; ++i) {
- uint256 value = values.unsafeMemoryAccess(i);
- unchecked {
- // Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i])
- _totalSupply[ids.unsafeMemoryAccess(i)] -= value;
- // Overflow not possible: sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll
- totalBurnValue += value;
- }
- }
- unchecked {
- // Overflow not possible: totalBurnValue = sum_i(values[i]) <= sum_i(totalSupply(ids[i])) <= totalSupplyAll
- _totalSupplyAll -= totalBurnValue;
- }
- }
- }
- }
|