ERC1155.test.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. const { accounts, contract } = require('@openzeppelin/test-environment');
  2. const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
  3. const { ZERO_ADDRESS } = constants;
  4. const { expect } = require('chai');
  5. const { shouldBehaveLikeERC1155 } = require('./ERC1155.behavior');
  6. const ERC1155Mock = contract.fromArtifact('ERC1155Mock');
  7. describe('ERC1155', function () {
  8. const [operator, tokenHolder, tokenBatchHolder, ...otherAccounts] = accounts;
  9. const initialURI = 'https://token-cdn-domain/{id}.json';
  10. beforeEach(async function () {
  11. this.token = await ERC1155Mock.new(initialURI);
  12. });
  13. shouldBehaveLikeERC1155(otherAccounts);
  14. describe('internal functions', function () {
  15. const tokenId = new BN(1990);
  16. const mintAmount = new BN(9001);
  17. const burnAmount = new BN(3000);
  18. const tokenBatchIds = [new BN(2000), new BN(2010), new BN(2020)];
  19. const mintAmounts = [new BN(5000), new BN(10000), new BN(42195)];
  20. const burnAmounts = [new BN(5000), new BN(9001), new BN(195)];
  21. const data = '0x12345678';
  22. describe('_mint', function () {
  23. it('reverts with a zero destination address', async function () {
  24. await expectRevert(
  25. this.token.mint(ZERO_ADDRESS, tokenId, mintAmount, data),
  26. 'ERC1155: mint to the zero address',
  27. );
  28. });
  29. context('with minted tokens', function () {
  30. beforeEach(async function () {
  31. ({ logs: this.logs } = await this.token.mint(tokenHolder, tokenId, mintAmount, data, { from: operator }));
  32. });
  33. it('emits a TransferSingle event', function () {
  34. expectEvent.inLogs(this.logs, 'TransferSingle', {
  35. operator,
  36. from: ZERO_ADDRESS,
  37. to: tokenHolder,
  38. id: tokenId,
  39. value: mintAmount,
  40. });
  41. });
  42. it('credits the minted amount of tokens', async function () {
  43. expect(await this.token.balanceOf(tokenHolder, tokenId)).to.be.bignumber.equal(mintAmount);
  44. });
  45. });
  46. });
  47. describe('_mintBatch', function () {
  48. it('reverts with a zero destination address', async function () {
  49. await expectRevert(
  50. this.token.mintBatch(ZERO_ADDRESS, tokenBatchIds, mintAmounts, data),
  51. 'ERC1155: mint to the zero address',
  52. );
  53. });
  54. it('reverts if length of inputs do not match', async function () {
  55. await expectRevert(
  56. this.token.mintBatch(tokenBatchHolder, tokenBatchIds, mintAmounts.slice(1), data),
  57. 'ERC1155: ids and amounts length mismatch',
  58. );
  59. await expectRevert(
  60. this.token.mintBatch(tokenBatchHolder, tokenBatchIds.slice(1), mintAmounts, data),
  61. 'ERC1155: ids and amounts length mismatch',
  62. );
  63. });
  64. context('with minted batch of tokens', function () {
  65. beforeEach(async function () {
  66. ({ logs: this.logs } = await this.token.mintBatch(
  67. tokenBatchHolder,
  68. tokenBatchIds,
  69. mintAmounts,
  70. data,
  71. { from: operator },
  72. ));
  73. });
  74. it('emits a TransferBatch event', function () {
  75. expectEvent.inLogs(this.logs, 'TransferBatch', {
  76. operator,
  77. from: ZERO_ADDRESS,
  78. to: tokenBatchHolder,
  79. });
  80. });
  81. it('credits the minted batch of tokens', async function () {
  82. const holderBatchBalances = await this.token.balanceOfBatch(
  83. new Array(tokenBatchIds.length).fill(tokenBatchHolder),
  84. tokenBatchIds,
  85. );
  86. for (let i = 0; i < holderBatchBalances.length; i++) {
  87. expect(holderBatchBalances[i]).to.be.bignumber.equal(mintAmounts[i]);
  88. }
  89. });
  90. });
  91. });
  92. describe('_burn', function () {
  93. it('reverts when burning the zero account\'s tokens', async function () {
  94. await expectRevert(
  95. this.token.burn(ZERO_ADDRESS, tokenId, mintAmount),
  96. 'ERC1155: burn from the zero address',
  97. );
  98. });
  99. it('reverts when burning a non-existent token id', async function () {
  100. await expectRevert(
  101. this.token.burn(tokenHolder, tokenId, mintAmount),
  102. 'ERC1155: burn amount exceeds balance',
  103. );
  104. });
  105. it('reverts when burning more than available tokens', async function () {
  106. await this.token.mint(
  107. tokenHolder,
  108. tokenId,
  109. mintAmount,
  110. data,
  111. { from: operator },
  112. );
  113. await expectRevert(
  114. this.token.burn(tokenHolder, tokenId, mintAmount.addn(1)),
  115. 'ERC1155: burn amount exceeds balance',
  116. );
  117. });
  118. context('with minted-then-burnt tokens', function () {
  119. beforeEach(async function () {
  120. await this.token.mint(tokenHolder, tokenId, mintAmount, data);
  121. ({ logs: this.logs } = await this.token.burn(
  122. tokenHolder,
  123. tokenId,
  124. burnAmount,
  125. { from: operator },
  126. ));
  127. });
  128. it('emits a TransferSingle event', function () {
  129. expectEvent.inLogs(this.logs, 'TransferSingle', {
  130. operator,
  131. from: tokenHolder,
  132. to: ZERO_ADDRESS,
  133. id: tokenId,
  134. value: burnAmount,
  135. });
  136. });
  137. it('accounts for both minting and burning', async function () {
  138. expect(await this.token.balanceOf(
  139. tokenHolder,
  140. tokenId,
  141. )).to.be.bignumber.equal(mintAmount.sub(burnAmount));
  142. });
  143. });
  144. });
  145. describe('_burnBatch', function () {
  146. it('reverts when burning the zero account\'s tokens', async function () {
  147. await expectRevert(
  148. this.token.burnBatch(ZERO_ADDRESS, tokenBatchIds, burnAmounts),
  149. 'ERC1155: burn from the zero address',
  150. );
  151. });
  152. it('reverts if length of inputs do not match', async function () {
  153. await expectRevert(
  154. this.token.burnBatch(tokenBatchHolder, tokenBatchIds, burnAmounts.slice(1)),
  155. 'ERC1155: ids and amounts length mismatch',
  156. );
  157. await expectRevert(
  158. this.token.burnBatch(tokenBatchHolder, tokenBatchIds.slice(1), burnAmounts),
  159. 'ERC1155: ids and amounts length mismatch',
  160. );
  161. });
  162. it('reverts when burning a non-existent token id', async function () {
  163. await expectRevert(
  164. this.token.burnBatch(tokenBatchHolder, tokenBatchIds, burnAmounts),
  165. 'ERC1155: burn amount exceeds balance',
  166. );
  167. });
  168. context('with minted-then-burnt tokens', function () {
  169. beforeEach(async function () {
  170. await this.token.mintBatch(tokenBatchHolder, tokenBatchIds, mintAmounts, data);
  171. ({ logs: this.logs } = await this.token.burnBatch(
  172. tokenBatchHolder,
  173. tokenBatchIds,
  174. burnAmounts,
  175. { from: operator },
  176. ));
  177. });
  178. it('emits a TransferBatch event', function () {
  179. expectEvent.inLogs(this.logs, 'TransferBatch', {
  180. operator,
  181. from: tokenBatchHolder,
  182. to: ZERO_ADDRESS,
  183. // ids: tokenBatchIds,
  184. // values: burnAmounts,
  185. });
  186. });
  187. it('accounts for both minting and burning', async function () {
  188. const holderBatchBalances = await this.token.balanceOfBatch(
  189. new Array(tokenBatchIds.length).fill(tokenBatchHolder),
  190. tokenBatchIds,
  191. );
  192. for (let i = 0; i < holderBatchBalances.length; i++) {
  193. expect(holderBatchBalances[i]).to.be.bignumber.equal(mintAmounts[i].sub(burnAmounts[i]));
  194. }
  195. });
  196. });
  197. });
  198. });
  199. describe('ERC1155MetadataURI', function () {
  200. const firstTokenID = new BN('42');
  201. const secondTokenID = new BN('1337');
  202. it('emits no URI event in constructor', async function () {
  203. await expectEvent.notEmitted.inConstruction(this.token, 'URI');
  204. });
  205. it('sets the initial URI for all token types', async function () {
  206. expect(await this.token.uri(firstTokenID)).to.be.equal(initialURI);
  207. expect(await this.token.uri(secondTokenID)).to.be.equal(initialURI);
  208. });
  209. describe('_setURI', function () {
  210. const newURI = 'https://token-cdn-domain/{locale}/{id}.json';
  211. it('emits no URI event', async function () {
  212. const receipt = await this.token.setURI(newURI);
  213. expectEvent.notEmitted(receipt, 'URI');
  214. });
  215. it('sets the new URI for all token types', async function () {
  216. await this.token.setURI(newURI);
  217. expect(await this.token.uri(firstTokenID)).to.be.equal(newURI);
  218. expect(await this.token.uri(secondTokenID)).to.be.equal(newURI);
  219. });
  220. });
  221. });
  222. });