const { ethers } = require('hardhat'); const { expect } = require('chai'); const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior'); function shouldBehaveLikeERC2981() { const royaltyFraction = 10n; shouldSupportInterfaces(['ERC2981']); describe('default royalty', function () { beforeEach(async function () { await this.token.$_setDefaultRoyalty(this.account1, royaltyFraction); }); it('checks royalty is set', async function () { expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([ this.account1.address, (this.salePrice * royaltyFraction) / 10_000n, ]); }); it('updates royalty amount', async function () { const newFraction = 25n; await this.token.$_setDefaultRoyalty(this.account1, newFraction); expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([ this.account1.address, (this.salePrice * newFraction) / 10_000n, ]); }); it('holds same royalty value for different tokens', async function () { const newFraction = 20n; await this.token.$_setDefaultRoyalty(this.account1, newFraction); expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal( await this.token.royaltyInfo(this.tokenId2, this.salePrice), ); }); it('Remove royalty information', async function () { const newValue = 0n; await this.token.$_deleteDefaultRoyalty(); expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([ethers.ZeroAddress, newValue]); expect(await this.token.royaltyInfo(this.tokenId2, this.salePrice)).to.deep.equal([ethers.ZeroAddress, newValue]); }); it('reverts if invalid parameters', async function () { const royaltyDenominator = await this.token.$_feeDenominator(); await expect(this.token.$_setDefaultRoyalty(ethers.ZeroAddress, royaltyFraction)) .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidDefaultRoyaltyReceiver') .withArgs(ethers.ZeroAddress); const anotherRoyaltyFraction = 11000n; await expect(this.token.$_setDefaultRoyalty(this.account1, anotherRoyaltyFraction)) .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidDefaultRoyalty') .withArgs(anotherRoyaltyFraction, royaltyDenominator); }); }); describe('token based royalty', function () { beforeEach(async function () { await this.token.$_setTokenRoyalty(this.tokenId1, this.account1, royaltyFraction); }); it('updates royalty amount', async function () { const newFraction = 25n; expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([ this.account1.address, (this.salePrice * royaltyFraction) / 10_000n, ]); await this.token.$_setTokenRoyalty(this.tokenId1, this.account1, newFraction); expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([ this.account1.address, (this.salePrice * newFraction) / 10_000n, ]); }); it('holds different values for different tokens', async function () { const newFraction = 20n; await this.token.$_setTokenRoyalty(this.tokenId2, this.account1, newFraction); expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.not.deep.equal( await this.token.royaltyInfo(this.tokenId2, this.salePrice), ); }); it('reverts if invalid parameters', async function () { const royaltyDenominator = await this.token.$_feeDenominator(); await expect(this.token.$_setTokenRoyalty(this.tokenId1, ethers.ZeroAddress, royaltyFraction)) .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidTokenRoyaltyReceiver') .withArgs(this.tokenId1, ethers.ZeroAddress); const anotherRoyaltyFraction = 11000n; await expect(this.token.$_setTokenRoyalty(this.tokenId1, this.account1, anotherRoyaltyFraction)) .to.be.revertedWithCustomError(this.token, 'ERC2981InvalidTokenRoyalty') .withArgs(this.tokenId1, anotherRoyaltyFraction, royaltyDenominator); }); it('can reset token after setting royalty', async function () { const newFraction = 30n; await this.token.$_setTokenRoyalty(this.tokenId1, this.account2, newFraction); // Tokens must have own information expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.deep.equal([ this.account2.address, (this.salePrice * newFraction) / 10_000n, ]); await this.token.$_setTokenRoyalty(this.tokenId2, this.account1, 0n); // Token must not share default information expect(await this.token.royaltyInfo(this.tokenId2, this.salePrice)).to.deep.equal([this.account1.address, 0n]); }); it('can hold default and token royalty information', async function () { const newFraction = 30n; await this.token.$_setTokenRoyalty(this.tokenId2, this.account2, newFraction); // Tokens must not have same values expect(await this.token.royaltyInfo(this.tokenId1, this.salePrice)).to.not.deep.equal([ this.account2.address, (this.salePrice * newFraction) / 10_000n, ]); // Updated token must have new values expect(await this.token.royaltyInfo(this.tokenId2, this.salePrice)).to.deep.equal([ this.account2.address, (this.salePrice * newFraction) / 10_000n, ]); }); }); } module.exports = { shouldBehaveLikeERC2981, };