ERC827Token.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  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 allow payment through transfer'
  91. , async function () {
  92. const message = await Message.new();
  93. const extraData = message.contract.buyMessage.getData(
  94. web3.toHex(123456), 666, 'Transfer Done'
  95. );
  96. const transaction = await token.transferAndCall(
  97. message.contract.address, 100, extraData, { from: accounts[0], value: 1000 }
  98. );
  99. assert.equal(2, transaction.receipt.logs.length);
  100. new BigNumber(100).should.be.bignumber.equal(
  101. await token.balanceOf(message.contract.address)
  102. );
  103. new BigNumber(1000).should.be.bignumber.equal(
  104. await web3.eth.getBalance(message.contract.address)
  105. );
  106. });
  107. it(
  108. 'should allow payment through approve'
  109. , async function () {
  110. const message = await Message.new();
  111. const extraData = message.contract.buyMessage.getData(
  112. web3.toHex(123456), 666, 'Transfer Done'
  113. );
  114. const transaction = await token.approveAndCall(
  115. message.contract.address, 100, extraData, { from: accounts[0], value: 1000 }
  116. );
  117. assert.equal(2, transaction.receipt.logs.length);
  118. new BigNumber(100).should.be.bignumber.equal(
  119. await token.allowance(accounts[0], message.contract.address)
  120. );
  121. new BigNumber(1000).should.be.bignumber.equal(
  122. await web3.eth.getBalance(message.contract.address)
  123. );
  124. });
  125. it(
  126. 'should allow payment through increaseApproval'
  127. , async function () {
  128. const message = await Message.new();
  129. const extraData = message.contract.buyMessage.getData(
  130. web3.toHex(123456), 666, 'Transfer Done'
  131. );
  132. await token.approve(message.contract.address, 10);
  133. new BigNumber(10).should.be.bignumber.equal(
  134. await token.allowance(accounts[0], message.contract.address)
  135. );
  136. const transaction = await token.increaseApprovalAndCall(
  137. message.contract.address, 50, extraData, { from: accounts[0], value: 1000 }
  138. );
  139. assert.equal(2, transaction.receipt.logs.length);
  140. new BigNumber(60).should.be.bignumber.equal(
  141. await token.allowance(accounts[0], message.contract.address)
  142. );
  143. new BigNumber(1000).should.be.bignumber.equal(
  144. await web3.eth.getBalance(message.contract.address)
  145. );
  146. });
  147. it(
  148. 'should allow payment through decreaseApproval'
  149. , async function () {
  150. const message = await Message.new();
  151. await token.approve(message.contract.address, 100);
  152. new BigNumber(100).should.be.bignumber.equal(
  153. await token.allowance(accounts[0], message.contract.address)
  154. );
  155. const extraData = message.contract.buyMessage.getData(
  156. web3.toHex(123456), 666, 'Transfer Done'
  157. );
  158. const transaction = await token.decreaseApprovalAndCall(
  159. message.contract.address, 60, extraData, { from: accounts[0], value: 1000 }
  160. );
  161. assert.equal(2, transaction.receipt.logs.length);
  162. new BigNumber(40).should.be.bignumber.equal(
  163. await token.allowance(accounts[0], message.contract.address)
  164. );
  165. new BigNumber(1000).should.be.bignumber.equal(
  166. await web3.eth.getBalance(message.contract.address)
  167. );
  168. });
  169. it(
  170. 'should allow payment through transferFrom'
  171. , async function () {
  172. const message = await Message.new();
  173. const extraData = message.contract.buyMessage.getData(
  174. web3.toHex(123456), 666, 'Transfer Done'
  175. );
  176. await token.approve(accounts[1], 100, { from: accounts[0] });
  177. new BigNumber(100).should.be.bignumber.equal(
  178. await token.allowance(accounts[0], accounts[1])
  179. );
  180. const transaction = await token.transferFromAndCall(
  181. accounts[0], message.contract.address, 100, extraData, { from: accounts[1], value: 1000 }
  182. );
  183. assert.equal(2, transaction.receipt.logs.length);
  184. new BigNumber(100).should.be.bignumber.equal(
  185. await token.balanceOf(message.contract.address)
  186. );
  187. new BigNumber(1000).should.be.bignumber.equal(
  188. await web3.eth.getBalance(message.contract.address)
  189. );
  190. });
  191. it('should revert funds of failure inside approve (with data)', async function () {
  192. const message = await Message.new();
  193. const extraData = message.contract.showMessage.getData(
  194. web3.toHex(123456), 666, 'Transfer Done'
  195. );
  196. await token.approveAndCall(
  197. message.contract.address, 10, extraData, { from: accounts[0], value: 1000 }
  198. ).should.be.rejectedWith(EVMRevert);
  199. // approval should not have gone through so allowance is still 0
  200. new BigNumber(0).should.be.bignumber
  201. .equal(await token.allowance(accounts[1], message.contract.address));
  202. new BigNumber(0).should.be.bignumber
  203. .equal(await web3.eth.getBalance(message.contract.address));
  204. });
  205. it('should revert funds of failure inside transfer (with data)', async function () {
  206. const message = await Message.new();
  207. const extraData = message.contract.showMessage.getData(
  208. web3.toHex(123456), 666, 'Transfer Done'
  209. );
  210. await token.transferAndCall(
  211. message.contract.address, 10, extraData, { from: accounts[0], value: 1000 }
  212. ).should.be.rejectedWith(EVMRevert);
  213. // transfer should not have gone through, so balance is still 0
  214. new BigNumber(0).should.be.bignumber
  215. .equal(await token.balanceOf(message.contract.address));
  216. new BigNumber(0).should.be.bignumber
  217. .equal(await web3.eth.getBalance(message.contract.address));
  218. });
  219. it('should revert funds of failure inside transferFrom (with data)', async function () {
  220. const message = await Message.new();
  221. const extraData = message.contract.showMessage.getData(
  222. web3.toHex(123456), 666, 'Transfer Done'
  223. );
  224. await token.approve(accounts[1], 10, { from: accounts[2] });
  225. await token.transferFromAndCall(
  226. accounts[2], message.contract.address, 10, extraData, { from: accounts[2], value: 1000 }
  227. ).should.be.rejectedWith(EVMRevert);
  228. // transferFrom should have failed so balance is still 0 but allowance is 10
  229. new BigNumber(10).should.be.bignumber
  230. .equal(await token.allowance(accounts[2], accounts[1]));
  231. new BigNumber(0).should.be.bignumber
  232. .equal(await token.balanceOf(message.contract.address));
  233. new BigNumber(0).should.be.bignumber
  234. .equal(await web3.eth.getBalance(message.contract.address));
  235. });
  236. it(
  237. 'should return correct balances after transfer (with data) and show the event on receiver contract'
  238. , async function () {
  239. const message = await Message.new();
  240. const extraData = message.contract.showMessage.getData(
  241. web3.toHex(123456), 666, 'Transfer Done'
  242. );
  243. const transaction = await token.transferAndCall(message.contract.address, 100, extraData);
  244. assert.equal(2, transaction.receipt.logs.length);
  245. new BigNumber(100).should.be.bignumber.equal(
  246. await token.balanceOf(message.contract.address)
  247. );
  248. });
  249. it(
  250. 'should return correct allowance after approve (with data) and show the event on receiver contract'
  251. , async function () {
  252. const message = await Message.new();
  253. const extraData = message.contract.showMessage.getData(
  254. web3.toHex(123456), 666, 'Transfer Done'
  255. );
  256. const transaction = await token.approveAndCall(message.contract.address, 100, extraData);
  257. assert.equal(2, transaction.receipt.logs.length);
  258. new BigNumber(100).should.be.bignumber.equal(
  259. await token.allowance(accounts[0], message.contract.address)
  260. );
  261. });
  262. it(
  263. 'should return correct allowance after increaseApproval (with data) and show the event on receiver contract'
  264. , async function () {
  265. const message = await Message.new();
  266. const extraData = message.contract.showMessage.getData(
  267. web3.toHex(123456), 666, 'Transfer Done'
  268. );
  269. await token.approve(message.contract.address, 10);
  270. new BigNumber(10).should.be.bignumber.equal(
  271. await token.allowance(accounts[0], message.contract.address)
  272. );
  273. const transaction = await token.increaseApprovalAndCall(message.contract.address, 50, extraData);
  274. assert.equal(2, transaction.receipt.logs.length);
  275. new BigNumber(60).should.be.bignumber.equal(
  276. await token.allowance(accounts[0], message.contract.address)
  277. );
  278. });
  279. it(
  280. 'should return correct allowance after decreaseApproval (with data) and show the event on receiver contract'
  281. , async function () {
  282. const message = await Message.new();
  283. await token.approve(message.contract.address, 100);
  284. new BigNumber(100).should.be.bignumber.equal(
  285. await token.allowance(accounts[0], message.contract.address)
  286. );
  287. const extraData = message.contract.showMessage.getData(
  288. web3.toHex(123456), 666, 'Transfer Done'
  289. );
  290. const transaction = await token.decreaseApprovalAndCall(message.contract.address, 60, extraData);
  291. assert.equal(2, transaction.receipt.logs.length);
  292. new BigNumber(40).should.be.bignumber.equal(
  293. await token.allowance(accounts[0], message.contract.address)
  294. );
  295. });
  296. it(
  297. 'should return correct balances after transferFrom (with data) and show the event on receiver contract'
  298. , async function () {
  299. const message = await Message.new();
  300. const extraData = message.contract.showMessage.getData(
  301. web3.toHex(123456), 666, 'Transfer Done'
  302. );
  303. await token.approve(accounts[1], 100, { from: accounts[0] });
  304. new BigNumber(100).should.be.bignumber.equal(
  305. await token.allowance(accounts[0], accounts[1])
  306. );
  307. const transaction = await token.transferFromAndCall(accounts[0], message.contract.address, 100, extraData, {
  308. from: accounts[1],
  309. });
  310. assert.equal(2, transaction.receipt.logs.length);
  311. new BigNumber(100).should.be.bignumber.equal(
  312. await token.balanceOf(message.contract.address)
  313. );
  314. });
  315. it('should fail inside approve (with data)', async function () {
  316. const message = await Message.new();
  317. const extraData = message.contract.fail.getData();
  318. await token.approveAndCall(message.contract.address, 10, extraData)
  319. .should.be.rejectedWith(EVMRevert);
  320. // approval should not have gone through so allowance is still 0
  321. new BigNumber(0).should.be.bignumber
  322. .equal(await token.allowance(accounts[1], message.contract.address));
  323. });
  324. it('should fail inside transfer (with data)', async function () {
  325. const message = await Message.new();
  326. const extraData = message.contract.fail.getData();
  327. await token.transferAndCall(message.contract.address, 10, extraData)
  328. .should.be.rejectedWith(EVMRevert);
  329. // transfer should not have gone through, so balance is still 0
  330. new BigNumber(0).should.be.bignumber
  331. .equal(await token.balanceOf(message.contract.address));
  332. });
  333. it('should fail inside transferFrom (with data)', async function () {
  334. const message = await Message.new();
  335. const extraData = message.contract.fail.getData();
  336. await token.approve(accounts[1], 10, { from: accounts[2] });
  337. await token.transferFromAndCall(accounts[2], message.contract.address, 10, extraData, { from: accounts[1] })
  338. .should.be.rejectedWith(EVMRevert);
  339. // transferFrom should have failed so balance is still 0 but allowance is 10
  340. new BigNumber(10).should.be.bignumber
  341. .equal(await token.allowance(accounts[2], accounts[1]));
  342. new BigNumber(0).should.be.bignumber
  343. .equal(await token.balanceOf(message.contract.address));
  344. });
  345. it('should fail approve (with data) when using token contract address as receiver', async function () {
  346. const message = await Message.new();
  347. const extraData = message.contract.showMessage.getData(
  348. web3.toHex(123456), 666, 'Transfer Done'
  349. );
  350. await token.approveAndCall(token.contract.address, 100, extraData, { from: accounts[0] })
  351. .should.be.rejectedWith(EVMRevert);
  352. });
  353. it('should fail transfer (with data) when using token contract address as receiver', async function () {
  354. const message = await Message.new();
  355. const extraData = message.contract.showMessage.getData(
  356. web3.toHex(123456), 666, 'Transfer Done'
  357. );
  358. await token.transferAndCall(token.contract.address, 100, extraData)
  359. .should.be.rejectedWith(EVMRevert);
  360. });
  361. it('should fail transferFrom (with data) when using token contract address as receiver', async function () {
  362. const message = await Message.new();
  363. const extraData = message.contract.showMessage.getData(
  364. web3.toHex(123456), 666, 'Transfer Done'
  365. );
  366. await token.approve(accounts[1], 1, { from: accounts[0] });
  367. await token.transferFromAndCall(accounts[0], token.contract.address, 1, extraData, { from: accounts[1] })
  368. .should.be.rejectedWith(EVMRevert);
  369. });
  370. });
  371. });