ERC2981.behavior.js 6.25 KB
Newer Older
vicotor's avatar
vicotor committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
const { BN, constants, expectRevert } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');
const { ZERO_ADDRESS } = constants;

const { shouldSupportInterfaces } = require('../../utils/introspection/SupportsInterface.behavior');

function shouldBehaveLikeERC2981 () {
  const royaltyFraction = new BN('10');

  shouldSupportInterfaces(['ERC2981']);

  describe('default royalty', function () {
    beforeEach(async function () {
      await this.token.setDefaultRoyalty(this.account1, royaltyFraction);
    });

    it('checks royalty is set', async function () {
      const royalty = new BN((this.salePrice * royaltyFraction) / 10000);

      const initInfo = await this.token.royaltyInfo(this.tokenId1, this.salePrice);

      expect(initInfo[0]).to.be.equal(this.account1);
      expect(initInfo[1]).to.be.bignumber.equal(royalty);
    });

    it('updates royalty amount', async function () {
      const newPercentage = new BN('25');

      // Updated royalty check
      await this.token.setDefaultRoyalty(this.account1, newPercentage);
      const royalty = new BN((this.salePrice * newPercentage) / 10000);
      const newInfo = await this.token.royaltyInfo(this.tokenId1, this.salePrice);

      expect(newInfo[0]).to.be.equal(this.account1);
      expect(newInfo[1]).to.be.bignumber.equal(royalty);
    });

    it('holds same royalty value for different tokens', async function () {
      const newPercentage = new BN('20');
      await this.token.setDefaultRoyalty(this.account1, newPercentage);

      const token1Info = await this.token.royaltyInfo(this.tokenId1, this.salePrice);
      const token2Info = await this.token.royaltyInfo(this.tokenId2, this.salePrice);

      expect(token1Info[1]).to.be.bignumber.equal(token2Info[1]);
    });

    it('Remove royalty information', async function () {
      const newValue = new BN('0');
      await this.token.deleteDefaultRoyalty();

      const token1Info = await this.token.royaltyInfo(this.tokenId1, this.salePrice);
      const token2Info = await this.token.royaltyInfo(this.tokenId2, this.salePrice);
      // Test royalty info is still persistent across all tokens
      expect(token1Info[0]).to.be.bignumber.equal(token2Info[0]);
      expect(token1Info[1]).to.be.bignumber.equal(token2Info[1]);
      // Test information was deleted
      expect(token1Info[0]).to.be.equal(ZERO_ADDRESS);
      expect(token1Info[1]).to.be.bignumber.equal(newValue);
    });

    it('reverts if invalid parameters', async function () {
      await expectRevert(
        this.token.setDefaultRoyalty(ZERO_ADDRESS, royaltyFraction),
        'ERC2981: invalid receiver',
      );

      await expectRevert(
        this.token.setDefaultRoyalty(this.account1, new BN('11000')),
        'ERC2981: royalty fee will exceed salePrice',
      );
    });
  });

  describe('token based royalty', function () {
    beforeEach(async function () {
      await this.token.setTokenRoyalty(this.tokenId1, this.account1, royaltyFraction);
    });

    it('updates royalty amount', async function () {
      const newPercentage = new BN('25');
      let royalty = new BN((this.salePrice * royaltyFraction) / 10000);
      // Initial royalty check
      const initInfo = await this.token.royaltyInfo(this.tokenId1, this.salePrice);

      expect(initInfo[0]).to.be.equal(this.account1);
      expect(initInfo[1]).to.be.bignumber.equal(royalty);

      // Updated royalty check
      await this.token.setTokenRoyalty(this.tokenId1, this.account1, newPercentage);
      royalty = new BN((this.salePrice * newPercentage) / 10000);
      const newInfo = await this.token.royaltyInfo(this.tokenId1, this.salePrice);

      expect(newInfo[0]).to.be.equal(this.account1);
      expect(newInfo[1]).to.be.bignumber.equal(royalty);
    });

    it('holds different values for different tokens', async function () {
      const newPercentage = new BN('20');
      await this.token.setTokenRoyalty(this.tokenId2, this.account1, newPercentage);

      const token1Info = await this.token.royaltyInfo(this.tokenId1, this.salePrice);
      const token2Info = await this.token.royaltyInfo(this.tokenId2, this.salePrice);

      // must be different even at the same this.salePrice
      expect(token1Info[1]).to.not.be.equal(token2Info.royaltyFraction);
    });

    it('reverts if invalid parameters', async function () {
      await expectRevert(
        this.token.setTokenRoyalty(this.tokenId1, ZERO_ADDRESS, royaltyFraction),
        'ERC2981: Invalid parameters',
      );

      await expectRevert(
        this.token.setTokenRoyalty(this.tokenId1, this.account1, new BN('11000')),
        'ERC2981: royalty fee will exceed salePrice',
      );
    });

    it('can reset token after setting royalty', async function () {
      const newPercentage = new BN('30');
      const royalty = new BN((this.salePrice * newPercentage) / 10000);
      await this.token.setTokenRoyalty(this.tokenId1, this.account2, newPercentage);

      const tokenInfo = await this.token.royaltyInfo(this.tokenId1, this.salePrice);

      // Tokens must have own information
      expect(tokenInfo[1]).to.be.bignumber.equal(royalty);
      expect(tokenInfo[0]).to.be.equal(this.account2);

      await this.token.setTokenRoyalty(this.tokenId2, this.account1, new BN('0'));
      const result = await this.token.royaltyInfo(this.tokenId2, this.salePrice);
      // Token must not share default information
      expect(result[0]).to.be.equal(this.account1);
      expect(result[1]).to.be.bignumber.equal(new BN('0'));
    });

    it('can hold default and token royalty information', async function () {
      const newPercentage = new BN('30');
      const royalty = new BN((this.salePrice * newPercentage) / 10000);

      await this.token.setTokenRoyalty(this.tokenId2, this.account2, newPercentage);

      const token1Info = await this.token.royaltyInfo(this.tokenId1, this.salePrice);
      const token2Info = await this.token.royaltyInfo(this.tokenId2, this.salePrice);
      // Tokens must not have same values
      expect(token1Info[1]).to.not.be.bignumber.equal(token2Info[1]);
      expect(token1Info[0]).to.not.be.equal(token2Info[0]);

      // Updated token must have new values
      expect(token2Info[0]).to.be.equal(this.account2);
      expect(token2Info[1]).to.be.bignumber.equal(royalty);
    });
  });
}

module.exports = {
  shouldBehaveLikeERC2981,
};