From 2ce3be2af260169697a018ed8b21720575e5847d Mon Sep 17 00:00:00 2001 From: ra-phael <10075759+ra-phael@users.noreply.github.com> Date: Wed, 7 Sep 2022 15:18:56 +0100 Subject: [PATCH 1/2] Allow burning by token owner in the badge example --- contracts/examples/Badge.sol | 9 ++++-- test/examples/Badge.ts | 63 +++++++++++++++++++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/contracts/examples/Badge.sol b/contracts/examples/Badge.sol index 655229b..cb6bdf9 100644 --- a/contracts/examples/Badge.sol +++ b/contracts/examples/Badge.sol @@ -17,6 +17,11 @@ contract Badge is ERC1238, ERC1238URIStorage { _; } + modifier onlyContractOwnerOrTokenOwner(address tokenOwner) { + require(msg.sender == owner || msg.sender == tokenOwner, "Unauthorized: sender is not the owner"); + _; + } + function supportsInterface(bytes4 interfaceId) public view @@ -98,7 +103,7 @@ contract Badge is ERC1238, ERC1238URIStorage { uint256 id, uint256 amount, bool deleteURI - ) external onlyOwner { + ) external onlyContractOwnerOrTokenOwner(from) { if (deleteURI) { _burnAndDeleteURI(from, id, amount); } else { @@ -111,7 +116,7 @@ contract Badge is ERC1238, ERC1238URIStorage { uint256[] calldata ids, uint256[] calldata amounts, bool deleteURI - ) external onlyOwner { + ) external onlyContractOwnerOrTokenOwner(from) { if (deleteURI) { _burnBatchAndDeleteURIs(from, ids, amounts); } else { diff --git a/test/examples/Badge.ts b/test/examples/Badge.ts index ce086f3..0c448fe 100644 --- a/test/examples/Badge.ts +++ b/test/examples/Badge.ts @@ -6,7 +6,7 @@ import type { Artifact } from "hardhat/types"; import { chainIds } from "../../hardhat.config"; import type { Badge } from "../../src/types/Badge"; import { ERC1238ReceiverMock } from "../../src/types/ERC1238ReceiverMock"; -import { getMintBatchApprovalSignature } from "../../src/utils/ERC1238Approval"; +import { getMintApprovalSignature, getMintBatchApprovalSignature } from "../../src/utils/ERC1238Approval"; import { toBN } from "../utils/test-utils"; const BASE_URI = "https://token-cdn-domain/{id}.json"; @@ -168,4 +168,65 @@ describe("Badge", function () { await expect(tx).to.emit(badge, "MintBatch").withArgs(admin.address, to[2], ids[2], amounts[2]); }); }); + + describe("Single Burn", () => { + const tokenAmount = toBN("2"); + const tokenURI = "https://your-domain-name.com/credentials/tokens/1"; + const tokenId = toBN("1234"); + let v: number, r: string, s: string; + + const burnAmount = toBN("1"); + beforeEach(async () => { + // tokenId = tokenId.add(1); + + ({ v, r, s } = await getMintApprovalSignature({ + erc1238ContractAddress: badge.address, + chainId, + signer: eoaRecipient, + id: tokenId, + amount: tokenAmount, + approvalExpiry, + })); + + await badge + .connect(admin) + .mintToEOA(eoaRecipient.address, tokenId, tokenAmount, v, r, s, approvalExpiry, tokenURI, []); + }); + + it("should let a token owner burn their tokens", async () => { + await badge.connect(eoaRecipient).burn(eoaRecipient.address, tokenId, burnAmount, false); + + expect(await badge.balanceOf(eoaRecipient.address, tokenId)).to.eq(tokenAmount.sub(burnAmount)); + }); + + it("should let a token owner burn their tokens and delete the URI", async () => { + expect(await badge.tokenURI(tokenId)).to.eq(tokenURI); + + await badge.connect(eoaRecipient).burn(eoaRecipient.address, tokenId, burnAmount, true); + + expect(await badge.balanceOf(eoaRecipient.address, tokenId)).to.eq(tokenAmount.sub(burnAmount)); + expect(await badge.tokenURI(tokenId)).to.eq(BASE_URI); + }); + + it("should let the token issuer burn a token", async () => { + await badge.connect(admin).burn(eoaRecipient.address, tokenId, burnAmount, false); + + expect(await badge.balanceOf(eoaRecipient.address, tokenId)).to.eq(tokenAmount.sub(burnAmount)); + }); + + it("should let the token issuer burn a token and delete the URI", async () => { + expect(await badge.tokenURI(tokenId)).to.eq(tokenURI); + + await badge.connect(admin).burn(eoaRecipient.address, tokenId, burnAmount, true); + + expect(await badge.balanceOf(eoaRecipient.address, tokenId)).to.eq(tokenAmount.sub(burnAmount)); + expect(await badge.tokenURI(tokenId)).to.eq(BASE_URI); + }); + + it("should not let an unauthorized address burn", async () => { + await expect(badge.connect(signer1).burn(eoaRecipient.address, tokenId, burnAmount, false)).to.be.revertedWith( + "Unauthorized: sender is not the owner", + ); + }); + }); }); From 9f304b64392a35c7c198fe59ada64325dd2bb270 Mon Sep 17 00:00:00 2001 From: ra-phael <10075759+ra-phael@users.noreply.github.com> Date: Wed, 7 Sep 2022 15:21:00 +0100 Subject: [PATCH 2/2] cleaning --- test/examples/Badge.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/examples/Badge.ts b/test/examples/Badge.ts index 0c448fe..99e0c72 100644 --- a/test/examples/Badge.ts +++ b/test/examples/Badge.ts @@ -173,12 +173,10 @@ describe("Badge", function () { const tokenAmount = toBN("2"); const tokenURI = "https://your-domain-name.com/credentials/tokens/1"; const tokenId = toBN("1234"); + const burnAmount = toBN("1"); let v: number, r: string, s: string; - const burnAmount = toBN("1"); beforeEach(async () => { - // tokenId = tokenId.add(1); - ({ v, r, s } = await getMintApprovalSignature({ erc1238ContractAddress: badge.address, chainId,