SmartToken.js 9.8 KB

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