// SPDX-License-Identifier: MIT // Klaytn Contract Library v1.0.0 (KIP/token/KIP37/extensions/KIP37Supply.sol) // Based on OpenZeppelin Contracts v4.5.0 (token/ERC1155/extensions/ERC1155Supply.sol) // https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v4.5.0 pragma solidity ^0.8.0; import "../KIP37.sol"; /** * @dev Extension of KIP37 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 are no guarantees in this contract that no other token with the * same id are not going to be minted. Additional supply capping logic should be used for this. */ abstract contract KIP37Supply is KIP37 { mapping(uint256 => uint256) private _totalSupply; /** * @dev Total amount of tokens in with a given id. */ function totalSupply(uint256 id) public view virtual returns (uint256) { return _totalSupply[id]; } /** * @dev Indicates whether any token exist with a given id, or not. */ function exists(uint256 id) public view virtual returns (bool) { return KIP37Supply.totalSupply(id) > 0; } /** * @dev See {KIP37-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual override { super._beforeTokenTransfer(operator, from, to, ids, amounts, data); if (from == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { _totalSupply[ids[i]] += amounts[i]; } } if (to == address(0)) { for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 supply = _totalSupply[id]; require(supply >= amount, "KIP37: burn amount exceeds totalSupply"); unchecked { _totalSupply[id] = supply - amount; } } } } }