Commit a7fcc27a by github-actions

Transpile 2ff6b149

parent b8d96a76
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* `Counter`: add a reset method. ([#2678](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2678)) * `Counter`: add a reset method. ([#2678](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2678))
* Tokens: Wrap definitely safe subtractions in `unchecked` blocks. * Tokens: Wrap definitely safe subtractions in `unchecked` blocks.
* `Math`: Add a `ceilDiv` method for performing ceiling division. * `Math`: Add a `ceilDiv` method for performing ceiling division.
* `ERC1155Supply`: add a new `ERC1155` extension that keeps track of the totalSupply of each tokenId. ([#2593](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2593))
### Breaking Changes ### Breaking Changes
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./ERC1155MockUpgradeable.sol";
import "../token/ERC1155/extensions/ERC1155SupplyUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
contract ERC1155SupplyMockUpgradeable is Initializable, ERC1155MockUpgradeable, ERC1155SupplyUpgradeable {
function __ERC1155SupplyMock_init(string memory uri) internal initializer {
__Context_init_unchained();
__ERC165_init_unchained();
__ERC1155_init_unchained(uri);
__ERC1155Mock_init_unchained(uri);
__ERC1155Supply_init_unchained();
__ERC1155SupplyMock_init_unchained(uri);
}
function __ERC1155SupplyMock_init_unchained(string memory uri) internal initializer { }
function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual override(ERC1155Upgradeable, ERC1155SupplyUpgradeable) {
super._mint(account, id, amount, data);
}
function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual override(ERC1155Upgradeable, ERC1155SupplyUpgradeable) {
super._mintBatch(to, ids, amounts, data);
}
function _burn(address account, uint256 id, uint256 amount) internal virtual override(ERC1155Upgradeable, ERC1155SupplyUpgradeable) {
super._burn(account, id, amount);
}
function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual override(ERC1155Upgradeable, ERC1155SupplyUpgradeable) {
super._burnBatch(account, ids, amounts);
}
uint256[50] private __gap;
}
...@@ -188,6 +188,13 @@ contract ERC1155MockUpgradeableWithInit is ERC1155MockUpgradeable { ...@@ -188,6 +188,13 @@ contract ERC1155MockUpgradeableWithInit is ERC1155MockUpgradeable {
__ERC1155Mock_init(uri); __ERC1155Mock_init(uri);
} }
} }
import "./ERC1155SupplyMockUpgradeable.sol";
contract ERC1155SupplyMockUpgradeableWithInit is ERC1155SupplyMockUpgradeable {
constructor(string memory uri) public payable {
__ERC1155SupplyMock_init(uri);
}
}
import "./ERC1155BurnableMockUpgradeable.sol"; import "./ERC1155BurnableMockUpgradeable.sol";
contract ERC1155BurnableMockUpgradeableWithInit is ERC1155BurnableMockUpgradeable { contract ERC1155BurnableMockUpgradeableWithInit is ERC1155BurnableMockUpgradeable {
......
...@@ -32,6 +32,8 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel ...@@ -32,6 +32,8 @@ NOTE: This core set of contracts is designed to be unopinionated, allowing devel
{{ERC1155Burnable}} {{ERC1155Burnable}}
{{ERC1155Supply}}
== Presets == Presets
These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code. These contracts are preconfigured combinations of the above features. They can be used through inheritance or as models to copy and paste their source code.
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../ERC1155Upgradeable.sol";
import "../../../proxy/utils/Initializable.sol";
/**
* @dev Extension of ERC1155 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.
*/
abstract contract ERC1155SupplyUpgradeable is Initializable, ERC1155Upgradeable {
function __ERC1155Supply_init() internal initializer {
__Context_init_unchained();
__ERC165_init_unchained();
__ERC1155Supply_init_unchained();
}
function __ERC1155Supply_init_unchained() internal initializer {
}
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 weither any token exist with a given id, or not.
*/
function exists(uint256 id) public view virtual returns(bool) {
return ERC1155SupplyUpgradeable.totalSupply(id) > 0;
}
/**
* @dev See {ERC1155-_mint}.
*/
function _mint(address account, uint256 id, uint256 amount, bytes memory data) internal virtual override {
super._mint(account, id, amount, data);
_totalSupply[id] += amount;
}
/**
* @dev See {ERC1155-_mintBatch}.
*/
function _mintBatch(address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) internal virtual override {
super._mintBatch(to, ids, amounts, data);
for (uint256 i = 0; i < ids.length; ++i) {
_totalSupply[ids[i]] += amounts[i];
}
}
/**
* @dev See {ERC1155-_burn}.
*/
function _burn(address account, uint256 id, uint256 amount) internal virtual override {
super._burn(account, id, amount);
_totalSupply[id] -= amount;
}
/**
* @dev See {ERC1155-_burnBatch}.
*/
function _burnBatch(address account, uint256[] memory ids, uint256[] memory amounts) internal virtual override {
super._burnBatch(account, ids, amounts);
for (uint256 i = 0; i < ids.length; ++i) {
_totalSupply[ids[i]] -= amounts[i];
}
}
uint256[49] private __gap;
}
...@@ -273,8 +273,8 @@ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeabl ...@@ -273,8 +273,8 @@ contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeabl
require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked { unchecked {
_balances[account] = accountBalance - amount; _balances[account] = accountBalance - amount;
_totalSupply -= amount;
} }
_totalSupply -= amount;
emit Transfer(account, address(0), amount); emit Transfer(account, address(0), amount);
} }
......
...@@ -431,8 +431,8 @@ contract ERC777Upgradeable is Initializable, ContextUpgradeable, IERC777Upgradea ...@@ -431,8 +431,8 @@ contract ERC777Upgradeable is Initializable, ContextUpgradeable, IERC777Upgradea
require(fromBalance >= amount, "ERC777: burn amount exceeds balance"); require(fromBalance >= amount, "ERC777: burn amount exceeds balance");
unchecked { unchecked {
_balances[from] = fromBalance - amount; _balances[from] = fromBalance - amount;
_totalSupply -= amount;
} }
_totalSupply -= amount;
emit Burned(operator, from, amount, data, operatorData); emit Burned(operator, from, amount, data, operatorData);
emit Transfer(from, address(0), amount); emit Transfer(from, address(0), amount);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
const { BN } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');
const ERC1155SupplyMock = artifacts.require('ERC1155SupplyMock');
contract('ERC1155Supply', function (accounts) {
const [ holder ] = accounts;
const uri = 'https://token.com';
const firstTokenId = new BN('37');
const firstTokenAmount = new BN('42');
const secondTokenId = new BN('19842');
const secondTokenAmount = new BN('23');
beforeEach(async function () {
this.token = await ERC1155SupplyMock.new(uri);
});
context('before mint', function () {
it('exist', async function () {
expect(await this.token.exists(firstTokenId)).to.be.equal(false);
});
it('totalSupply', async function () {
expect(await this.token.totalSupply(firstTokenId)).to.be.bignumber.equal('0');
});
});
context('after mint', function () {
context('single', function () {
beforeEach(async function () {
await this.token.mint(holder, firstTokenId, firstTokenAmount, '0x');
});
it('exist', async function () {
expect(await this.token.exists(firstTokenId)).to.be.equal(true);
});
it('totalSupply', async function () {
expect(await this.token.totalSupply(firstTokenId)).to.be.bignumber.equal(firstTokenAmount);
});
});
context('batch', function () {
beforeEach(async function () {
await this.token.mintBatch(
holder,
[ firstTokenId, secondTokenId ],
[ firstTokenAmount, secondTokenAmount ],
'0x',
);
});
it('exist', async function () {
expect(await this.token.exists(firstTokenId)).to.be.equal(true);
expect(await this.token.exists(secondTokenId)).to.be.equal(true);
});
it('totalSupply', async function () {
expect(await this.token.totalSupply(firstTokenId)).to.be.bignumber.equal(firstTokenAmount);
expect(await this.token.totalSupply(secondTokenId)).to.be.bignumber.equal(secondTokenAmount);
});
});
});
context('after burn', function () {
context('single', function () {
beforeEach(async function () {
await this.token.mint(holder, firstTokenId, firstTokenAmount, '0x');
await this.token.burn(holder, firstTokenId, firstTokenAmount);
});
it('exist', async function () {
expect(await this.token.exists(firstTokenId)).to.be.equal(false);
});
it('totalSupply', async function () {
expect(await this.token.totalSupply(firstTokenId)).to.be.bignumber.equal('0');
});
});
context('batch', function () {
beforeEach(async function () {
await this.token.mintBatch(
holder,
[ firstTokenId, secondTokenId ],
[ firstTokenAmount, secondTokenAmount ],
'0x',
);
await this.token.burnBatch(
holder,
[ firstTokenId, secondTokenId ],
[ firstTokenAmount, secondTokenAmount ],
);
});
it('exist', async function () {
expect(await this.token.exists(firstTokenId)).to.be.equal(false);
expect(await this.token.exists(secondTokenId)).to.be.equal(false);
});
it('totalSupply', async function () {
expect(await this.token.totalSupply(firstTokenId)).to.be.bignumber.equal('0');
expect(await this.token.totalSupply(secondTokenId)).to.be.bignumber.equal('0');
});
});
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment