ERC827Token.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. import EVMRevert from '../../helpers/EVMRevert';
  2. var Message = artifacts.require('MessageHelper');
  3. var ERC827TokenMock = artifacts.require('ERC827TokenMock');
  4. var BigNumber = web3.BigNumber;
  5. require('chai')
  6. .use(require('chai-as-promised'))
  7. .use(require('chai-bignumber')(BigNumber))
  8. .should();
  9. contract('ERC827 Token', function (accounts) {
  10. let token;
  11. beforeEach(async function () {
  12. token = await ERC827TokenMock.new(accounts[0], 100);
  13. });
  14. it('should return the correct totalSupply after construction', async function () {
  15. let totalSupply = await token.totalSupply();
  16. assert.equal(totalSupply, 100);
  17. });
  18. it('should return the correct allowance amount after approval', async function () {
  19. let token = await ERC827TokenMock.new(accounts[0], 100);
  20. await token.approve(accounts[1], 100);
  21. let allowance = await token.allowance(accounts[0], accounts[1]);
  22. assert.equal(allowance, 100);
  23. });
  24. it('should return correct balances after transfer', async function () {
  25. await token.transfer(accounts[1], 100);
  26. let balance0 = await token.balanceOf(accounts[0]);
  27. assert.equal(balance0, 0);
  28. let balance1 = await token.balanceOf(accounts[1]);
  29. assert.equal(balance1, 100);
  30. });
  31. it('should throw an error when trying to transfer more than balance', async function () {
  32. await token.transfer(accounts[1], 101).should.be.rejectedWith(EVMRevert);
  33. });
  34. it('should return correct balances after transfering from another account', async function () {
  35. await token.approve(accounts[1], 100);
  36. await token.transferFrom(accounts[0], accounts[2], 100, { from: accounts[1] });
  37. let balance0 = await token.balanceOf(accounts[0]);
  38. assert.equal(balance0, 0);
  39. let balance1 = await token.balanceOf(accounts[2]);
  40. assert.equal(balance1, 100);
  41. let balance2 = await token.balanceOf(accounts[1]);
  42. assert.equal(balance2, 0);
  43. });
  44. it('should throw an error when trying to transfer more than allowed', async function () {
  45. await token.approve(accounts[1], 99);
  46. await token.transferFrom(
  47. accounts[0], accounts[2], 100,
  48. { from: accounts[1] }
  49. ).should.be.rejectedWith(EVMRevert);
  50. });
  51. it('should throw an error when trying to transferFrom more than _from has', async function () {
  52. let balance0 = await token.balanceOf(accounts[0]);
  53. await token.approve(accounts[1], 99);
  54. await token.transferFrom(
  55. accounts[0], accounts[2], balance0 + 1,
  56. { from: accounts[1] }
  57. ).should.be.rejectedWith(EVMRevert);
  58. });
  59. describe('validating allowance updates to spender', function () {
  60. let preApproved;
  61. it('should start with zero', async function () {
  62. preApproved = await token.allowance(accounts[0], accounts[1]);
  63. assert.equal(preApproved, 0);
  64. });
  65. it('should increase by 50 then decrease by 10', async function () {
  66. await token.increaseApproval(accounts[1], 50);
  67. let postIncrease = await token.allowance(accounts[0], accounts[1]);
  68. preApproved.plus(50).should.be.bignumber.equal(postIncrease);
  69. await token.decreaseApproval(accounts[1], 10);
  70. let postDecrease = await token.allowance(accounts[0], accounts[1]);
  71. postIncrease.minus(10).should.be.bignumber.equal(postDecrease);
  72. });
  73. });
  74. it('should increase by 50 then set to 0 when decreasing by more than 50', async function () {
  75. await token.approve(accounts[1], 50);
  76. await token.decreaseApproval(accounts[1], 60);
  77. let postDecrease = await token.allowance(accounts[0], accounts[1]);
  78. postDecrease.should.be.bignumber.equal(0);
  79. });
  80. it('should throw an error when trying to transfer to 0x0', async function () {
  81. await token.transfer(0x0, 100).should.be.rejectedWith(EVMRevert);
  82. });
  83. it('should throw an error when trying to transferFrom to 0x0', async function () {
  84. await token.approve(accounts[1], 100);
  85. await token.transferFrom(accounts[0], 0x0, 100, { from: accounts[1] })
  86. .should.be.rejectedWith(EVMRevert);
  87. });
  88. describe('Test ERC827 methods', function () {
  89. it(
  90. 'should return correct balances after transfer (with data) and show the event on receiver contract'
  91. , async function () {
  92. const message = await Message.new();
  93. const extraData = message.contract.showMessage.getData(
  94. web3.toHex(123456), 666, 'Transfer Done'
  95. );
  96. const transaction = await token.transferAndCall(message.contract.address, 100, extraData);
  97. assert.equal(2, transaction.receipt.logs.length);
  98. new BigNumber(100).should.be.bignumber.equal(
  99. await token.balanceOf(message.contract.address)
  100. );
  101. });
  102. it(
  103. 'should return correct allowance after approve (with data) and show the event on receiver contract'
  104. , async function () {
  105. const message = await Message.new();
  106. const extraData = message.contract.showMessage.getData(
  107. web3.toHex(123456), 666, 'Transfer Done'
  108. );
  109. const transaction = await token.approveAndCall(message.contract.address, 100, extraData);
  110. assert.equal(2, transaction.receipt.logs.length);
  111. new BigNumber(100).should.be.bignumber.equal(
  112. await token.allowance(accounts[0], message.contract.address)
  113. );
  114. });
  115. it(
  116. 'should return correct allowance after increaseApproval (with data) and show the event on receiver contract'
  117. , async function () {
  118. const message = await Message.new();
  119. const extraData = message.contract.showMessage.getData(
  120. web3.toHex(123456), 666, 'Transfer Done'
  121. );
  122. await token.approve(message.contract.address, 10);
  123. new BigNumber(10).should.be.bignumber.equal(
  124. await token.allowance(accounts[0], message.contract.address)
  125. );
  126. const transaction = await token.increaseApprovalAndCall(message.contract.address, 50, extraData);
  127. assert.equal(2, transaction.receipt.logs.length);
  128. new BigNumber(60).should.be.bignumber.equal(
  129. await token.allowance(accounts[0], message.contract.address)
  130. );
  131. });
  132. it(
  133. 'should return correct allowance after decreaseApproval (with data) and show the event on receiver contract'
  134. , async function () {
  135. const message = await Message.new();
  136. await token.approve(message.contract.address, 100);
  137. new BigNumber(100).should.be.bignumber.equal(
  138. await token.allowance(accounts[0], message.contract.address)
  139. );
  140. const extraData = message.contract.showMessage.getData(
  141. web3.toHex(123456), 666, 'Transfer Done'
  142. );
  143. const transaction = await token.decreaseApprovalAndCall(message.contract.address, 60, extraData);
  144. assert.equal(2, transaction.receipt.logs.length);
  145. new BigNumber(40).should.be.bignumber.equal(
  146. await token.allowance(accounts[0], message.contract.address)
  147. );
  148. });
  149. it(
  150. 'should return correct balances after transferFrom (with data) and show the event on receiver contract'
  151. , async function () {
  152. const message = await Message.new();
  153. const extraData = message.contract.showMessage.getData(
  154. web3.toHex(123456), 666, 'Transfer Done'
  155. );
  156. await token.approve(accounts[1], 100, { from: accounts[0] });
  157. new BigNumber(100).should.be.bignumber.equal(
  158. await token.allowance(accounts[0], accounts[1])
  159. );
  160. const transaction = await token.transferFromAndCall(accounts[0], message.contract.address, 100, extraData, {
  161. from: accounts[1],
  162. });
  163. assert.equal(2, transaction.receipt.logs.length);
  164. new BigNumber(100).should.be.bignumber.equal(
  165. await token.balanceOf(message.contract.address)
  166. );
  167. });
  168. it('should fail inside approve (with data)', async function () {
  169. const message = await Message.new();
  170. const extraData = message.contract.fail.getData();
  171. await token.approveAndCall(message.contract.address, 10, extraData)
  172. .should.be.rejectedWith(EVMRevert);
  173. // approval should not have gone through so allowance is still 0
  174. new BigNumber(0).should.be.bignumber
  175. .equal(await token.allowance(accounts[1], message.contract.address));
  176. });
  177. it('should fail inside transfer (with data)', async function () {
  178. const message = await Message.new();
  179. const extraData = message.contract.fail.getData();
  180. await token.transferAndCall(message.contract.address, 10, extraData)
  181. .should.be.rejectedWith(EVMRevert);
  182. // transfer should not have gone through, so balance is still 0
  183. new BigNumber(0).should.be.bignumber
  184. .equal(await token.balanceOf(message.contract.address));
  185. });
  186. it('should fail inside transferFrom (with data)', async function () {
  187. const message = await Message.new();
  188. const extraData = message.contract.fail.getData();
  189. await token.approve(accounts[1], 10, { from: accounts[2] });
  190. await token.transferFromAndCall(accounts[2], message.contract.address, 10, extraData, { from: accounts[1] })
  191. .should.be.rejectedWith(EVMRevert);
  192. // transferFrom should have failed so balance is still 0 but allowance is 10
  193. new BigNumber(10).should.be.bignumber
  194. .equal(await token.allowance(accounts[2], accounts[1]));
  195. new BigNumber(0).should.be.bignumber
  196. .equal(await token.balanceOf(message.contract.address));
  197. });
  198. it('should fail approve (with data) when using token contract address as receiver', async function () {
  199. const message = await Message.new();
  200. const extraData = message.contract.showMessage.getData(
  201. web3.toHex(123456), 666, 'Transfer Done'
  202. );
  203. await token.approveAndCall(token.contract.address, 100, extraData, { from: accounts[0] })
  204. .should.be.rejectedWith(EVMRevert);
  205. });
  206. it('should fail transfer (with data) when using token contract address as receiver', async function () {
  207. const message = await Message.new();
  208. const extraData = message.contract.showMessage.getData(
  209. web3.toHex(123456), 666, 'Transfer Done'
  210. );
  211. await token.transferAndCall(token.contract.address, 100, extraData)
  212. .should.be.rejectedWith(EVMRevert);
  213. });
  214. it('should fail transferFrom (with data) when using token contract address as receiver', async function () {
  215. const message = await Message.new();
  216. const extraData = message.contract.showMessage.getData(
  217. web3.toHex(123456), 666, 'Transfer Done'
  218. );
  219. await token.approve(accounts[1], 1, { from: accounts[0] });
  220. await token.transferFromAndCall(accounts[0], token.contract.address, 1, extraData, { from: accounts[1] })
  221. .should.be.rejectedWith(EVMRevert);
  222. });
  223. });
  224. });