diff --git a/contracts/mocks/ERC3525_Testing.sol b/contracts/mocks/ERC3525_Testing.sol index bfd5f2e..d54801a 100644 --- a/contracts/mocks/ERC3525_Testing.sol +++ b/contracts/mocks/ERC3525_Testing.sol @@ -53,6 +53,14 @@ contract ERC3525_Testing is ERC3525SlotEnumerableUpgradeable { return _isApprovedOrOwner(operator_, tokenId_); } + function splitValue(uint256 fromToken_, uint256 value_) public virtual returns (uint256 tokenId) { + return _splitValue(fromToken_, value_); + } + + function mergeValue(uint256 fromToken_, uint256 toToken_) public virtual returns (uint256 tokenId) { + return _mergeValue(fromToken_, toToken_); + } + function slotURI( uint256 /*slot_*/ ) public pure override returns (string memory) { diff --git a/test/erc3525/ERC3525.burn.ts b/test/erc3525/ERC3525.burn.ts index 84fb763..7685933 100644 --- a/test/erc3525/ERC3525.burn.ts +++ b/test/erc3525/ERC3525.burn.ts @@ -25,5 +25,18 @@ export function shouldBehaveLikeSemiFungibleTokenBurn(): void { await expect(user.sft.burn(2)).to.be.revertedWith("NotApprovedOrOwner"); }); + + it("doesnt reallocate value after a token is burnt", async function () { + const { sft, user, anon } = await setupTestERC3525(); + await sft.mintValue(user.address, 1, 10); + + expect(await sft.ownerOf(1)).to.equal(user.address); + await user.sft["transferFrom(uint256,address,uint256)"](1, anon.address, 5); + expect(await sft.ownerOf(2)).to.equal(anon.address); + + await anon.sft.burn(2); + expect((await sft["balanceOf(address)"](anon.address)).isZero()).to.be.true; + expect((await sft["balanceOf(uint256)"](1)).toNumber()).to.equal(5); + }); }); } diff --git a/test/erc3525/ERC3525.mint.ts b/test/erc3525/ERC3525.mint.ts index 6baa08f..444bf6d 100644 --- a/test/erc3525/ERC3525.mint.ts +++ b/test/erc3525/ERC3525.mint.ts @@ -44,5 +44,19 @@ export function shouldBehaveLikeSemiFungibleTokenMint(): void { expect(await sft["balanceOf(uint256)"](1)).to.be.eq("1000000"); expect(await sft["balanceOf(uint256)"](2)).to.be.eq("2000000"); }); + + it("enumerates slots correctly", async function () { + const { sft, user, anon } = await setupTestERC3525(); + await sft.mintValue(user.address, 1, 10); + await user.sft["transferFrom(uint256,address,uint256)"](1, anon.address, 5); + expect(await sft.ownerOf(1)).to.be.eq(user.address); + expect(await sft.ownerOf(2)).to.be.eq(anon.address); + expect(await sft["tokenInSlotByIndex"](1, 0)).to.be.eq("1"); + expect(await sft.totalSupply()).to.be.eq(2); + + //these fail: + //expect(await sft["tokenInSlotByIndex"](1, 1)).to.be.eq("2"); //reverts + expect(await sft.tokenSupplyInSlot(1)).to.be.eq(2); //returns 1 + }); }); } diff --git a/test/erc3525/ERC3525.transfer.ts b/test/erc3525/ERC3525.transfer.ts index 43f4ec4..66cf29c 100644 --- a/test/erc3525/ERC3525.transfer.ts +++ b/test/erc3525/ERC3525.transfer.ts @@ -66,5 +66,18 @@ export function shouldBehaveLikeSemiFungibleTokenTransfer(): void { expect(await sft["balanceOf(uint256)"](1)).to.be.eq("500000"); expect(await sft["balanceOf(uint256)"](2)).to.be.eq("500000"); }); + + it("doesnt decrease total supply after nfts have been merged", async function () { + const { sft, user } = await setupTestERC3525(); + await sft.mintValue(user.address, 1, 10); + await user.sft.splitValue(1, 5); + expect(await sft["balanceOf(address)"](user.address)).to.be.equal(2); + await user.sft.mergeValue(2, 1); + await user.sft.burn(2); + expect(await sft["balanceOf(address)"](user.address)).to.be.equal(1); + + //fails: totalSupply is still 2 + expect(await sft.totalSupply()).to.be.equal(1); + }); }); } diff --git a/test/hypercert_minter/HyperCertMinter.split.merge.ts b/test/hypercert_minter/HyperCertMinter.split.merge.ts index 8349936..a9033c1 100644 --- a/test/hypercert_minter/HyperCertMinter.split.merge.ts +++ b/test/hypercert_minter/HyperCertMinter.split.merge.ts @@ -73,4 +73,25 @@ export function shouldBehaveLikeHypercertMinterSplitAndMerge(): void { expect(await minter["balanceOf(uint256)"](3)).to.be.eq("50"); expect(await minter.tokenSupplyInSlot(slot)).to.be.eq(2); }); + + it("doesnt decrease total supply after nfts have been merged", async function () { + const { user, minter, anon } = await setupTest(); + const claim = await newClaim({ fractions: [10] }); + const data = encodeClaim(claim); + + await minter.mint(user.address, data); + await user.minter["transferFrom(uint256,address,uint256)"](1, anon.address, 5); + expect(await minter["balanceOf(address)"](user.address)).to.be.equal(1); + expect(await minter["balanceOf(address)"](anon.address)).to.be.equal(1); + expect(await minter.totalSupply()).to.be.equal(2); + + await anon.minter["safeTransferFrom(address,address,uint256)"](anon.address, user.address, 2); + await user.minter.merge([2, 1]); + expect(await minter["balanceOf(address)"](user.address)).to.be.equal(1); + expect(await minter["balanceOf(address)"](anon.address)).to.be.equal(0); + expect(await minter["balanceOf(uint256)"](1)).to.be.equal(10); + + //fails: totalSupply is still 2 + expect(await minter.totalSupply()).to.be.equal(1); + }); }