Skip to content

Commit

Permalink
Merge pull request #531 from nevermined-io/fix/burn_provenance
Browse files Browse the repository at this point in the history
Avoiding provenance id collisions on NFT-1155 operations
  • Loading branch information
aaitor authored Feb 2, 2024
2 parents 7d68f6f + 32178c3 commit e2409c3
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 8 deletions.
12 changes: 8 additions & 4 deletions contracts/token/erc1155/NFT1155SubscriptionUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@ contract NFT1155SubscriptionUpgradeable is NFT1155Upgradeable {

function burn(uint256 id, uint256 amount) override public {
burn(_msgSender(), id, amount);
}
}

function burn(address to, uint256 id, uint256 amount) override public {
burn(to, id, amount, 0);
}

function burn(address to, uint256 id, uint256 amount, uint256 seed) override public {
require(balanceOf(to, id) >= amount, 'ERC1155: burn amount exceeds balance');
require(
isOperator(_msgSender()) || // Or the DIDRegistry is burning the NFT
Expand All @@ -72,7 +76,7 @@ contract NFT1155SubscriptionUpgradeable is NFT1155Upgradeable {
_nftAttributes[id].nftSupply -= amount;
// Register provenance event
nftRegistry.used(
keccak256(abi.encode(id, _msgSender(), 'burn', amount, block.number)),
keccak256(abi.encode(id, _msgSender(), 'burn', amount, block.number, seed, _nftAttributes[id].nftSupply)),
bytes32(id), _msgSender(), keccak256('burn'), '', 'burn');

bytes32 _key = _getTokenKey(to, id);
Expand Down Expand Up @@ -153,7 +157,7 @@ contract NFT1155SubscriptionUpgradeable is NFT1155Upgradeable {
) external {
require(ids.length == amounts.length, 'burnBatch: lengths do not match');
for (uint i = 0; i < ids.length; i++) {
burn(from, ids[i], amounts[i]);
burn(from, ids[i], amounts[i], i);
}
}
}
10 changes: 7 additions & 3 deletions contracts/token/erc1155/NFT1155Upgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ contract NFT1155Upgradeable is ERC1155Upgradeable, NFTBase {
_nftAttributes[id].nftSupply += amount;
// Register provenance event
nftRegistry.used(
keccak256(abi.encode(id, _msgSender(), 'mint', amount, block.number)),
keccak256(abi.encode(id, _msgSender(), 'mint', amount, block.number, _nftAttributes[id].nftSupply, data)),
bytes32(id), _msgSender(), keccak256('mint'), '', 'mint');

_mint(to, id, amount, data);
Expand All @@ -151,8 +151,12 @@ contract NFT1155Upgradeable is ERC1155Upgradeable, NFTBase {
function burn(uint256 id, uint256 amount) virtual public {
burn(_msgSender(), id, amount);
}

function burn(address to, uint256 id, uint256 amount) virtual public {
burn(to, id, amount, 0);
}

function burn(address to, uint256 id, uint256 amount, uint256 seed) virtual public {
require(balanceOf(to, id) >= amount, 'ERC1155: burn amount exceeds balance');
require(
isOperator(_msgSender()) || // Or the DIDRegistry is burning the NFT
Expand All @@ -166,7 +170,7 @@ contract NFT1155Upgradeable is ERC1155Upgradeable, NFTBase {
_nftAttributes[id].nftSupply -= amount;
// Register provenance event
nftRegistry.used(
keccak256(abi.encode(id, _msgSender(), 'burn', amount, block.number)),
keccak256(abi.encode(id, _msgSender(), 'burn', amount, block.number, seed, _nftAttributes[id].nftSupply)),
bytes32(id), _msgSender(), keccak256('burn'), '', 'burn');

_burn(to, id, amount);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nevermined-io/contracts",
"version": "3.5.5",
"version": "3.5.6",
"description": "Nevermined implementation of Nevermined in Solidity",
"bugs": {
"url": "https://github.com/nevermined-io/contracts/issues"
Expand Down
25 changes: 25 additions & 0 deletions test/unit/token/NFT1155Subscription.Test.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,5 +331,30 @@ contract('NFT1155 Subscription', (accounts) => {
}
assert.strictEqual(minted.length, 4)
})

it('Multiple tokens can be burned without generating provenance issues', async () => {
await setupTest()

const didSeed5 = testUtils.generateId()
const tokenId5 = await didRegistry.hashDID(didSeed5, minter)
await didRegistry.methods[
'registerMintableDID(bytes32,address,bytes32,address[],string,uint256,uint256,bool,bytes32,string,string)'
](didSeed5, nft.address, checksum, [], url, 0, 0, false, constants.activities.GENERATED, '', '', { from: minter })

const currentBlockNumber = await ethers.provider.getBlockNumber()

// We MINT 10 tokens
await nft.methods[
'mint(address,uint256,uint256,uint256,bytes)'
](account2, tokenId5, 10, currentBlockNumber + blocksExpiring, data, { from: minter })

// We BURN 1 tokens 2 times
await nft.burnBatch(account2, [tokenId5, tokenId5], [1, 1], { from: minter })
await increaseTime.mineBlocks(web3, 2)

// Balance is 8
const balance = new BigNumber(await nft.balanceOf(account2, tokenId5))
assert.strictEqual(balance.toNumber(), 10 - 2)
})
})
})

0 comments on commit e2409c3

Please sign in to comment.