SafeERC20.test.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. const { expectRevert } = require('@openzeppelin/test-helpers');
  2. const ERC20ReturnFalseMock = artifacts.require('ERC20ReturnFalseMock');
  3. const ERC20ReturnTrueMock = artifacts.require('ERC20ReturnTrueMock');
  4. const ERC20NoReturnMock = artifacts.require('ERC20NoReturnMock');
  5. const SafeERC20Wrapper = artifacts.require('SafeERC20Wrapper');
  6. contract('SafeERC20', function (accounts) {
  7. const [ hasNoCode ] = accounts;
  8. describe('with address that has no contract code', function () {
  9. beforeEach(async function () {
  10. this.wrapper = await SafeERC20Wrapper.new(hasNoCode);
  11. });
  12. shouldRevertOnAllCalls('Address: call to non-contract');
  13. });
  14. describe('with token that returns false on all calls', function () {
  15. beforeEach(async function () {
  16. this.wrapper = await SafeERC20Wrapper.new((await ERC20ReturnFalseMock.new()).address);
  17. });
  18. shouldRevertOnAllCalls('SafeERC20: ERC20 operation did not succeed');
  19. });
  20. describe('with token that returns true on all calls', function () {
  21. beforeEach(async function () {
  22. this.wrapper = await SafeERC20Wrapper.new((await ERC20ReturnTrueMock.new()).address);
  23. });
  24. shouldOnlyRevertOnErrors();
  25. });
  26. describe('with token that returns no boolean values', function () {
  27. beforeEach(async function () {
  28. this.wrapper = await SafeERC20Wrapper.new((await ERC20NoReturnMock.new()).address);
  29. });
  30. shouldOnlyRevertOnErrors();
  31. });
  32. });
  33. function shouldRevertOnAllCalls (reason) {
  34. it('reverts on transfer', async function () {
  35. await expectRevert(this.wrapper.transfer(), reason);
  36. });
  37. it('reverts on transferFrom', async function () {
  38. await expectRevert(this.wrapper.transferFrom(), reason);
  39. });
  40. it('reverts on approve', async function () {
  41. await expectRevert(this.wrapper.approve(0), reason);
  42. });
  43. it('reverts on increaseAllowance', async function () {
  44. // [TODO] make sure it's reverting for the right reason
  45. await expectRevert.unspecified(this.wrapper.increaseAllowance(0));
  46. });
  47. it('reverts on decreaseAllowance', async function () {
  48. // [TODO] make sure it's reverting for the right reason
  49. await expectRevert.unspecified(this.wrapper.decreaseAllowance(0));
  50. });
  51. }
  52. function shouldOnlyRevertOnErrors () {
  53. it('doesn\'t revert on transfer', async function () {
  54. await this.wrapper.transfer();
  55. });
  56. it('doesn\'t revert on transferFrom', async function () {
  57. await this.wrapper.transferFrom();
  58. });
  59. describe('approvals', function () {
  60. context('with zero allowance', function () {
  61. beforeEach(async function () {
  62. await this.wrapper.setAllowance(0);
  63. });
  64. it('doesn\'t revert when approving a non-zero allowance', async function () {
  65. await this.wrapper.approve(100);
  66. });
  67. it('doesn\'t revert when approving a zero allowance', async function () {
  68. await this.wrapper.approve(0);
  69. });
  70. it('doesn\'t revert when increasing the allowance', async function () {
  71. await this.wrapper.increaseAllowance(10);
  72. });
  73. it('reverts when decreasing the allowance', async function () {
  74. await expectRevert(
  75. this.wrapper.decreaseAllowance(10),
  76. 'SafeERC20: decreased allowance below zero'
  77. );
  78. });
  79. });
  80. context('with non-zero allowance', function () {
  81. beforeEach(async function () {
  82. await this.wrapper.setAllowance(100);
  83. });
  84. it('reverts when approving a non-zero allowance', async function () {
  85. await expectRevert(
  86. this.wrapper.approve(20),
  87. 'SafeERC20: approve from non-zero to non-zero allowance'
  88. );
  89. });
  90. it('doesn\'t revert when approving a zero allowance', async function () {
  91. await this.wrapper.approve(0);
  92. });
  93. it('doesn\'t revert when increasing the allowance', async function () {
  94. await this.wrapper.increaseAllowance(10);
  95. });
  96. it('doesn\'t revert when decreasing the allowance to a positive value', async function () {
  97. await this.wrapper.decreaseAllowance(50);
  98. });
  99. it('reverts when decreasing the allowance to a negative value', async function () {
  100. await expectRevert(
  101. this.wrapper.decreaseAllowance(200),
  102. 'SafeERC20: decreased allowance below zero'
  103. );
  104. });
  105. });
  106. });
  107. }