ERC1155.test.js 8.5 KB

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