ERC1155.behavior.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. const { BN, constants, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');
  2. const { ZERO_ADDRESS } = constants;
  3. const { expect } = require('chai');
  4. const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior');
  5. const ERC1155ReceiverMock = artifacts.require('ERC1155ReceiverMock');
  6. function shouldBehaveLikeERC1155 ([minter, firstTokenHolder, secondTokenHolder, multiTokenHolder, recipient, proxy]) {
  7. const firstTokenId = new BN(1);
  8. const secondTokenId = new BN(2);
  9. const unknownTokenId = new BN(3);
  10. const firstAmount = new BN(1000);
  11. const secondAmount = new BN(2000);
  12. const RECEIVER_SINGLE_MAGIC_VALUE = '0xf23a6e61';
  13. const RECEIVER_BATCH_MAGIC_VALUE = '0xbc197c81';
  14. describe('like an ERC1155', function () {
  15. describe('balanceOf', function () {
  16. it('reverts when queried about the zero address', async function () {
  17. await expectRevert(
  18. this.token.balanceOf(ZERO_ADDRESS, firstTokenId),
  19. 'ERC1155: balance query for the zero address',
  20. );
  21. });
  22. context('when accounts don\'t own tokens', function () {
  23. it('returns zero for given addresses', async function () {
  24. expect(await this.token.balanceOf(
  25. firstTokenHolder,
  26. firstTokenId,
  27. )).to.be.bignumber.equal('0');
  28. expect(await this.token.balanceOf(
  29. secondTokenHolder,
  30. secondTokenId,
  31. )).to.be.bignumber.equal('0');
  32. expect(await this.token.balanceOf(
  33. firstTokenHolder,
  34. unknownTokenId,
  35. )).to.be.bignumber.equal('0');
  36. });
  37. });
  38. context('when accounts own some tokens', function () {
  39. beforeEach(async function () {
  40. await this.token.mint(firstTokenHolder, firstTokenId, firstAmount, '0x', {
  41. from: minter,
  42. });
  43. await this.token.mint(
  44. secondTokenHolder,
  45. secondTokenId,
  46. secondAmount,
  47. '0x',
  48. {
  49. from: minter,
  50. },
  51. );
  52. });
  53. it('returns the amount of tokens owned by the given addresses', async function () {
  54. expect(await this.token.balanceOf(
  55. firstTokenHolder,
  56. firstTokenId,
  57. )).to.be.bignumber.equal(firstAmount);
  58. expect(await this.token.balanceOf(
  59. secondTokenHolder,
  60. secondTokenId,
  61. )).to.be.bignumber.equal(secondAmount);
  62. expect(await this.token.balanceOf(
  63. firstTokenHolder,
  64. unknownTokenId,
  65. )).to.be.bignumber.equal('0');
  66. });
  67. });
  68. });
  69. describe('balanceOfBatch', function () {
  70. it('reverts when input arrays don\'t match up', async function () {
  71. await expectRevert(
  72. this.token.balanceOfBatch(
  73. [firstTokenHolder, secondTokenHolder, firstTokenHolder, secondTokenHolder],
  74. [firstTokenId, secondTokenId, unknownTokenId],
  75. ),
  76. 'ERC1155: accounts and ids length mismatch',
  77. );
  78. await expectRevert(
  79. this.token.balanceOfBatch(
  80. [firstTokenHolder, secondTokenHolder],
  81. [firstTokenId, secondTokenId, unknownTokenId],
  82. ),
  83. 'ERC1155: accounts and ids length mismatch',
  84. );
  85. });
  86. it('reverts when one of the addresses is the zero address', async function () {
  87. await expectRevert(
  88. this.token.balanceOfBatch(
  89. [firstTokenHolder, secondTokenHolder, ZERO_ADDRESS],
  90. [firstTokenId, secondTokenId, unknownTokenId],
  91. ),
  92. 'ERC1155: batch balance query for the zero address',
  93. );
  94. });
  95. context('when accounts don\'t own tokens', function () {
  96. it('returns zeros for each account', async function () {
  97. const result = await this.token.balanceOfBatch(
  98. [firstTokenHolder, secondTokenHolder, firstTokenHolder],
  99. [firstTokenId, secondTokenId, unknownTokenId],
  100. );
  101. expect(result).to.be.an('array');
  102. expect(result[0]).to.be.a.bignumber.equal('0');
  103. expect(result[1]).to.be.a.bignumber.equal('0');
  104. expect(result[2]).to.be.a.bignumber.equal('0');
  105. });
  106. });
  107. context('when accounts own some tokens', function () {
  108. beforeEach(async function () {
  109. await this.token.mint(firstTokenHolder, firstTokenId, firstAmount, '0x', {
  110. from: minter,
  111. });
  112. await this.token.mint(
  113. secondTokenHolder,
  114. secondTokenId,
  115. secondAmount,
  116. '0x',
  117. {
  118. from: minter,
  119. },
  120. );
  121. });
  122. it('returns amounts owned by each account in order passed', async function () {
  123. const result = await this.token.balanceOfBatch(
  124. [secondTokenHolder, firstTokenHolder, firstTokenHolder],
  125. [secondTokenId, firstTokenId, unknownTokenId],
  126. );
  127. expect(result).to.be.an('array');
  128. expect(result[0]).to.be.a.bignumber.equal(secondAmount);
  129. expect(result[1]).to.be.a.bignumber.equal(firstAmount);
  130. expect(result[2]).to.be.a.bignumber.equal('0');
  131. });
  132. it('returns multiple times the balance of the same address when asked', async function () {
  133. const result = await this.token.balanceOfBatch(
  134. [firstTokenHolder, secondTokenHolder, firstTokenHolder],
  135. [firstTokenId, secondTokenId, firstTokenId],
  136. );
  137. expect(result).to.be.an('array');
  138. expect(result[0]).to.be.a.bignumber.equal(result[2]);
  139. expect(result[0]).to.be.a.bignumber.equal(firstAmount);
  140. expect(result[1]).to.be.a.bignumber.equal(secondAmount);
  141. expect(result[2]).to.be.a.bignumber.equal(firstAmount);
  142. });
  143. });
  144. });
  145. describe('setApprovalForAll', function () {
  146. let logs;
  147. beforeEach(async function () {
  148. ({ logs } = await this.token.setApprovalForAll(proxy, true, { from: multiTokenHolder }));
  149. });
  150. it('sets approval status which can be queried via isApprovedForAll', async function () {
  151. expect(await this.token.isApprovedForAll(multiTokenHolder, proxy)).to.be.equal(true);
  152. });
  153. it('emits an ApprovalForAll log', function () {
  154. expectEvent.inLogs(logs, 'ApprovalForAll', { account: multiTokenHolder, operator: proxy, approved: true });
  155. });
  156. it('can unset approval for an operator', async function () {
  157. await this.token.setApprovalForAll(proxy, false, { from: multiTokenHolder });
  158. expect(await this.token.isApprovedForAll(multiTokenHolder, proxy)).to.be.equal(false);
  159. });
  160. it('reverts if attempting to approve self as an operator', async function () {
  161. await expectRevert(
  162. this.token.setApprovalForAll(multiTokenHolder, true, { from: multiTokenHolder }),
  163. 'ERC1155: setting approval status for self',
  164. );
  165. });
  166. });
  167. describe('safeTransferFrom', function () {
  168. beforeEach(async function () {
  169. await this.token.mint(multiTokenHolder, firstTokenId, firstAmount, '0x', {
  170. from: minter,
  171. });
  172. await this.token.mint(
  173. multiTokenHolder,
  174. secondTokenId,
  175. secondAmount,
  176. '0x',
  177. {
  178. from: minter,
  179. },
  180. );
  181. });
  182. it('reverts when transferring more than balance', async function () {
  183. await expectRevert(
  184. this.token.safeTransferFrom(
  185. multiTokenHolder,
  186. recipient,
  187. firstTokenId,
  188. firstAmount.addn(1),
  189. '0x',
  190. { from: multiTokenHolder },
  191. ),
  192. 'ERC1155: insufficient balance for transfer',
  193. );
  194. });
  195. it('reverts when transferring to zero address', async function () {
  196. await expectRevert(
  197. this.token.safeTransferFrom(
  198. multiTokenHolder,
  199. ZERO_ADDRESS,
  200. firstTokenId,
  201. firstAmount,
  202. '0x',
  203. { from: multiTokenHolder },
  204. ),
  205. 'ERC1155: transfer to the zero address',
  206. );
  207. });
  208. function transferWasSuccessful ({ operator, from, id, value }) {
  209. it('debits transferred balance from sender', async function () {
  210. const newBalance = await this.token.balanceOf(from, id);
  211. expect(newBalance).to.be.a.bignumber.equal('0');
  212. });
  213. it('credits transferred balance to receiver', async function () {
  214. const newBalance = await this.token.balanceOf(this.toWhom, id);
  215. expect(newBalance).to.be.a.bignumber.equal(value);
  216. });
  217. it('emits a TransferSingle log', function () {
  218. expectEvent.inLogs(this.transferLogs, 'TransferSingle', {
  219. operator,
  220. from,
  221. to: this.toWhom,
  222. id,
  223. value,
  224. });
  225. });
  226. }
  227. context('when called by the multiTokenHolder', async function () {
  228. beforeEach(async function () {
  229. this.toWhom = recipient;
  230. ({ logs: this.transferLogs } =
  231. await this.token.safeTransferFrom(multiTokenHolder, recipient, firstTokenId, firstAmount, '0x', {
  232. from: multiTokenHolder,
  233. }));
  234. });
  235. transferWasSuccessful.call(this, {
  236. operator: multiTokenHolder,
  237. from: multiTokenHolder,
  238. id: firstTokenId,
  239. value: firstAmount,
  240. });
  241. it('preserves existing balances which are not transferred by multiTokenHolder', async function () {
  242. const balance1 = await this.token.balanceOf(multiTokenHolder, secondTokenId);
  243. expect(balance1).to.be.a.bignumber.equal(secondAmount);
  244. const balance2 = await this.token.balanceOf(recipient, secondTokenId);
  245. expect(balance2).to.be.a.bignumber.equal('0');
  246. });
  247. });
  248. context('when called by an operator on behalf of the multiTokenHolder', function () {
  249. context('when operator is not approved by multiTokenHolder', function () {
  250. beforeEach(async function () {
  251. await this.token.setApprovalForAll(proxy, false, { from: multiTokenHolder });
  252. });
  253. it('reverts', async function () {
  254. await expectRevert(
  255. this.token.safeTransferFrom(multiTokenHolder, recipient, firstTokenId, firstAmount, '0x', {
  256. from: proxy,
  257. }),
  258. 'ERC1155: caller is not owner nor approved',
  259. );
  260. });
  261. });
  262. context('when operator is approved by multiTokenHolder', function () {
  263. beforeEach(async function () {
  264. this.toWhom = recipient;
  265. await this.token.setApprovalForAll(proxy, true, { from: multiTokenHolder });
  266. ({ logs: this.transferLogs } =
  267. await this.token.safeTransferFrom(multiTokenHolder, recipient, firstTokenId, firstAmount, '0x', {
  268. from: proxy,
  269. }));
  270. });
  271. transferWasSuccessful.call(this, {
  272. operator: proxy,
  273. from: multiTokenHolder,
  274. id: firstTokenId,
  275. value: firstAmount,
  276. });
  277. it('preserves operator\'s balances not involved in the transfer', async function () {
  278. const balance1 = await this.token.balanceOf(proxy, firstTokenId);
  279. expect(balance1).to.be.a.bignumber.equal('0');
  280. const balance2 = await this.token.balanceOf(proxy, secondTokenId);
  281. expect(balance2).to.be.a.bignumber.equal('0');
  282. });
  283. });
  284. });
  285. context('when sending to a valid receiver', function () {
  286. beforeEach(async function () {
  287. this.receiver = await ERC1155ReceiverMock.new(
  288. RECEIVER_SINGLE_MAGIC_VALUE, false,
  289. RECEIVER_BATCH_MAGIC_VALUE, false,
  290. );
  291. });
  292. context('without data', function () {
  293. beforeEach(async function () {
  294. this.toWhom = this.receiver.address;
  295. this.transferReceipt = await this.token.safeTransferFrom(
  296. multiTokenHolder,
  297. this.receiver.address,
  298. firstTokenId,
  299. firstAmount,
  300. '0x',
  301. { from: multiTokenHolder },
  302. );
  303. ({ logs: this.transferLogs } = this.transferReceipt);
  304. });
  305. transferWasSuccessful.call(this, {
  306. operator: multiTokenHolder,
  307. from: multiTokenHolder,
  308. id: firstTokenId,
  309. value: firstAmount,
  310. });
  311. it('calls onERC1155Received', async function () {
  312. await expectEvent.inTransaction(this.transferReceipt.tx, ERC1155ReceiverMock, 'Received', {
  313. operator: multiTokenHolder,
  314. from: multiTokenHolder,
  315. id: firstTokenId,
  316. value: firstAmount,
  317. data: null,
  318. });
  319. });
  320. });
  321. context('with data', function () {
  322. const data = '0xf00dd00d';
  323. beforeEach(async function () {
  324. this.toWhom = this.receiver.address;
  325. this.transferReceipt = await this.token.safeTransferFrom(
  326. multiTokenHolder,
  327. this.receiver.address,
  328. firstTokenId,
  329. firstAmount,
  330. data,
  331. { from: multiTokenHolder },
  332. );
  333. ({ logs: this.transferLogs } = this.transferReceipt);
  334. });
  335. transferWasSuccessful.call(this, {
  336. operator: multiTokenHolder,
  337. from: multiTokenHolder,
  338. id: firstTokenId,
  339. value: firstAmount,
  340. });
  341. it('calls onERC1155Received', async function () {
  342. await expectEvent.inTransaction(this.transferReceipt.tx, ERC1155ReceiverMock, 'Received', {
  343. operator: multiTokenHolder,
  344. from: multiTokenHolder,
  345. id: firstTokenId,
  346. value: firstAmount,
  347. data,
  348. });
  349. });
  350. });
  351. });
  352. context('to a receiver contract returning unexpected value', function () {
  353. beforeEach(async function () {
  354. this.receiver = await ERC1155ReceiverMock.new(
  355. '0x00c0ffee', false,
  356. RECEIVER_BATCH_MAGIC_VALUE, false,
  357. );
  358. });
  359. it('reverts', async function () {
  360. await expectRevert(
  361. this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstAmount, '0x', {
  362. from: multiTokenHolder,
  363. }),
  364. 'ERC1155: ERC1155Receiver rejected tokens',
  365. );
  366. });
  367. });
  368. context('to a receiver contract that reverts', function () {
  369. beforeEach(async function () {
  370. this.receiver = await ERC1155ReceiverMock.new(
  371. RECEIVER_SINGLE_MAGIC_VALUE, true,
  372. RECEIVER_BATCH_MAGIC_VALUE, false,
  373. );
  374. });
  375. it('reverts', async function () {
  376. await expectRevert(
  377. this.token.safeTransferFrom(multiTokenHolder, this.receiver.address, firstTokenId, firstAmount, '0x', {
  378. from: multiTokenHolder,
  379. }),
  380. 'ERC1155ReceiverMock: reverting on receive',
  381. );
  382. });
  383. });
  384. context('to a contract that does not implement the required function', function () {
  385. it('reverts', async function () {
  386. const invalidReceiver = this.token;
  387. await expectRevert.unspecified(
  388. this.token.safeTransferFrom(multiTokenHolder, invalidReceiver.address, firstTokenId, firstAmount, '0x', {
  389. from: multiTokenHolder,
  390. }),
  391. );
  392. });
  393. });
  394. });
  395. describe('safeBatchTransferFrom', function () {
  396. beforeEach(async function () {
  397. await this.token.mint(multiTokenHolder, firstTokenId, firstAmount, '0x', {
  398. from: minter,
  399. });
  400. await this.token.mint(
  401. multiTokenHolder,
  402. secondTokenId,
  403. secondAmount,
  404. '0x',
  405. {
  406. from: minter,
  407. },
  408. );
  409. });
  410. it('reverts when transferring amount more than any of balances', async function () {
  411. await expectRevert(
  412. this.token.safeBatchTransferFrom(
  413. multiTokenHolder, recipient,
  414. [firstTokenId, secondTokenId],
  415. [firstAmount, secondAmount.addn(1)],
  416. '0x', { from: multiTokenHolder },
  417. ),
  418. 'ERC1155: insufficient balance for transfer',
  419. );
  420. });
  421. it('reverts when ids array length doesn\'t match amounts array length', async function () {
  422. await expectRevert(
  423. this.token.safeBatchTransferFrom(
  424. multiTokenHolder, recipient,
  425. [firstTokenId],
  426. [firstAmount, secondAmount],
  427. '0x', { from: multiTokenHolder },
  428. ),
  429. 'ERC1155: ids and amounts length mismatch',
  430. );
  431. await expectRevert(
  432. this.token.safeBatchTransferFrom(
  433. multiTokenHolder, recipient,
  434. [firstTokenId, secondTokenId],
  435. [firstAmount],
  436. '0x', { from: multiTokenHolder },
  437. ),
  438. 'ERC1155: ids and amounts length mismatch',
  439. );
  440. });
  441. it('reverts when transferring to zero address', async function () {
  442. await expectRevert(
  443. this.token.safeBatchTransferFrom(
  444. multiTokenHolder, ZERO_ADDRESS,
  445. [firstTokenId, secondTokenId],
  446. [firstAmount, secondAmount],
  447. '0x', { from: multiTokenHolder },
  448. ),
  449. 'ERC1155: transfer to the zero address',
  450. );
  451. });
  452. function batchTransferWasSuccessful ({ operator, from, ids, values }) {
  453. it('debits transferred balances from sender', async function () {
  454. const newBalances = await this.token.balanceOfBatch(new Array(ids.length).fill(from), ids);
  455. for (const newBalance of newBalances) {
  456. expect(newBalance).to.be.a.bignumber.equal('0');
  457. }
  458. });
  459. it('credits transferred balances to receiver', async function () {
  460. const newBalances = await this.token.balanceOfBatch(new Array(ids.length).fill(this.toWhom), ids);
  461. for (let i = 0; i < newBalances.length; i++) {
  462. expect(newBalances[i]).to.be.a.bignumber.equal(values[i]);
  463. }
  464. });
  465. it('emits a TransferBatch log', function () {
  466. expectEvent.inLogs(this.transferLogs, 'TransferBatch', {
  467. operator,
  468. from,
  469. to: this.toWhom,
  470. // ids,
  471. // values,
  472. });
  473. });
  474. }
  475. context('when called by the multiTokenHolder', async function () {
  476. beforeEach(async function () {
  477. this.toWhom = recipient;
  478. ({ logs: this.transferLogs } =
  479. await this.token.safeBatchTransferFrom(
  480. multiTokenHolder, recipient,
  481. [firstTokenId, secondTokenId],
  482. [firstAmount, secondAmount],
  483. '0x', { from: multiTokenHolder },
  484. ));
  485. });
  486. batchTransferWasSuccessful.call(this, {
  487. operator: multiTokenHolder,
  488. from: multiTokenHolder,
  489. ids: [firstTokenId, secondTokenId],
  490. values: [firstAmount, secondAmount],
  491. });
  492. });
  493. context('when called by an operator on behalf of the multiTokenHolder', function () {
  494. context('when operator is not approved by multiTokenHolder', function () {
  495. beforeEach(async function () {
  496. await this.token.setApprovalForAll(proxy, false, { from: multiTokenHolder });
  497. });
  498. it('reverts', async function () {
  499. await expectRevert(
  500. this.token.safeBatchTransferFrom(
  501. multiTokenHolder, recipient,
  502. [firstTokenId, secondTokenId],
  503. [firstAmount, secondAmount],
  504. '0x', { from: proxy },
  505. ),
  506. 'ERC1155: transfer caller is not owner nor approved',
  507. );
  508. });
  509. });
  510. context('when operator is approved by multiTokenHolder', function () {
  511. beforeEach(async function () {
  512. this.toWhom = recipient;
  513. await this.token.setApprovalForAll(proxy, true, { from: multiTokenHolder });
  514. ({ logs: this.transferLogs } =
  515. await this.token.safeBatchTransferFrom(
  516. multiTokenHolder, recipient,
  517. [firstTokenId, secondTokenId],
  518. [firstAmount, secondAmount],
  519. '0x', { from: proxy },
  520. ));
  521. });
  522. batchTransferWasSuccessful.call(this, {
  523. operator: proxy,
  524. from: multiTokenHolder,
  525. ids: [firstTokenId, secondTokenId],
  526. values: [firstAmount, secondAmount],
  527. });
  528. it('preserves operator\'s balances not involved in the transfer', async function () {
  529. const balance1 = await this.token.balanceOf(proxy, firstTokenId);
  530. expect(balance1).to.be.a.bignumber.equal('0');
  531. const balance2 = await this.token.balanceOf(proxy, secondTokenId);
  532. expect(balance2).to.be.a.bignumber.equal('0');
  533. });
  534. });
  535. });
  536. context('when sending to a valid receiver', function () {
  537. beforeEach(async function () {
  538. this.receiver = await ERC1155ReceiverMock.new(
  539. RECEIVER_SINGLE_MAGIC_VALUE, false,
  540. RECEIVER_BATCH_MAGIC_VALUE, false,
  541. );
  542. });
  543. context('without data', function () {
  544. beforeEach(async function () {
  545. this.toWhom = this.receiver.address;
  546. this.transferReceipt = await this.token.safeBatchTransferFrom(
  547. multiTokenHolder, this.receiver.address,
  548. [firstTokenId, secondTokenId],
  549. [firstAmount, secondAmount],
  550. '0x', { from: multiTokenHolder },
  551. );
  552. ({ logs: this.transferLogs } = this.transferReceipt);
  553. });
  554. batchTransferWasSuccessful.call(this, {
  555. operator: multiTokenHolder,
  556. from: multiTokenHolder,
  557. ids: [firstTokenId, secondTokenId],
  558. values: [firstAmount, secondAmount],
  559. });
  560. it('calls onERC1155BatchReceived', async function () {
  561. await expectEvent.inTransaction(this.transferReceipt.tx, ERC1155ReceiverMock, 'BatchReceived', {
  562. operator: multiTokenHolder,
  563. from: multiTokenHolder,
  564. // ids: [firstTokenId, secondTokenId],
  565. // values: [firstAmount, secondAmount],
  566. data: null,
  567. });
  568. });
  569. });
  570. context('with data', function () {
  571. const data = '0xf00dd00d';
  572. beforeEach(async function () {
  573. this.toWhom = this.receiver.address;
  574. this.transferReceipt = await this.token.safeBatchTransferFrom(
  575. multiTokenHolder, this.receiver.address,
  576. [firstTokenId, secondTokenId],
  577. [firstAmount, secondAmount],
  578. data, { from: multiTokenHolder },
  579. );
  580. ({ logs: this.transferLogs } = this.transferReceipt);
  581. });
  582. batchTransferWasSuccessful.call(this, {
  583. operator: multiTokenHolder,
  584. from: multiTokenHolder,
  585. ids: [firstTokenId, secondTokenId],
  586. values: [firstAmount, secondAmount],
  587. });
  588. it('calls onERC1155Received', async function () {
  589. await expectEvent.inTransaction(this.transferReceipt.tx, ERC1155ReceiverMock, 'BatchReceived', {
  590. operator: multiTokenHolder,
  591. from: multiTokenHolder,
  592. // ids: [firstTokenId, secondTokenId],
  593. // values: [firstAmount, secondAmount],
  594. data,
  595. });
  596. });
  597. });
  598. });
  599. context('to a receiver contract returning unexpected value', function () {
  600. beforeEach(async function () {
  601. this.receiver = await ERC1155ReceiverMock.new(
  602. RECEIVER_SINGLE_MAGIC_VALUE, false,
  603. RECEIVER_SINGLE_MAGIC_VALUE, false,
  604. );
  605. });
  606. it('reverts', async function () {
  607. await expectRevert(
  608. this.token.safeBatchTransferFrom(
  609. multiTokenHolder, this.receiver.address,
  610. [firstTokenId, secondTokenId],
  611. [firstAmount, secondAmount],
  612. '0x', { from: multiTokenHolder },
  613. ),
  614. 'ERC1155: ERC1155Receiver rejected tokens',
  615. );
  616. });
  617. });
  618. context('to a receiver contract that reverts', function () {
  619. beforeEach(async function () {
  620. this.receiver = await ERC1155ReceiverMock.new(
  621. RECEIVER_SINGLE_MAGIC_VALUE, false,
  622. RECEIVER_BATCH_MAGIC_VALUE, true,
  623. );
  624. });
  625. it('reverts', async function () {
  626. await expectRevert(
  627. this.token.safeBatchTransferFrom(
  628. multiTokenHolder, this.receiver.address,
  629. [firstTokenId, secondTokenId],
  630. [firstAmount, secondAmount],
  631. '0x', { from: multiTokenHolder },
  632. ),
  633. 'ERC1155ReceiverMock: reverting on batch receive',
  634. );
  635. });
  636. });
  637. context('to a receiver contract that reverts only on single transfers', function () {
  638. beforeEach(async function () {
  639. this.receiver = await ERC1155ReceiverMock.new(
  640. RECEIVER_SINGLE_MAGIC_VALUE, true,
  641. RECEIVER_BATCH_MAGIC_VALUE, false,
  642. );
  643. this.toWhom = this.receiver.address;
  644. this.transferReceipt = await this.token.safeBatchTransferFrom(
  645. multiTokenHolder, this.receiver.address,
  646. [firstTokenId, secondTokenId],
  647. [firstAmount, secondAmount],
  648. '0x', { from: multiTokenHolder },
  649. );
  650. ({ logs: this.transferLogs } = this.transferReceipt);
  651. });
  652. batchTransferWasSuccessful.call(this, {
  653. operator: multiTokenHolder,
  654. from: multiTokenHolder,
  655. ids: [firstTokenId, secondTokenId],
  656. values: [firstAmount, secondAmount],
  657. });
  658. it('calls onERC1155BatchReceived', async function () {
  659. await expectEvent.inTransaction(this.transferReceipt.tx, ERC1155ReceiverMock, 'BatchReceived', {
  660. operator: multiTokenHolder,
  661. from: multiTokenHolder,
  662. // ids: [firstTokenId, secondTokenId],
  663. // values: [firstAmount, secondAmount],
  664. data: null,
  665. });
  666. });
  667. });
  668. context('to a contract that does not implement the required function', function () {
  669. it('reverts', async function () {
  670. const invalidReceiver = this.token;
  671. await expectRevert.unspecified(
  672. this.token.safeBatchTransferFrom(
  673. multiTokenHolder, invalidReceiver.address,
  674. [firstTokenId, secondTokenId],
  675. [firstAmount, secondAmount],
  676. '0x', { from: multiTokenHolder },
  677. ),
  678. );
  679. });
  680. });
  681. });
  682. shouldSupportInterfaces(['ERC165', 'ERC1155']);
  683. });
  684. }
  685. module.exports = {
  686. shouldBehaveLikeERC1155,
  687. };