Math.test.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. const { BN, constants, expectRevert } = require('@openzeppelin/test-helpers');
  2. const { expect } = require('chai');
  3. const { MAX_UINT256 } = constants;
  4. const { Rounding } = require('../../helpers/enums.js');
  5. const MathMock = artifacts.require('MathMock');
  6. contract('Math', function (accounts) {
  7. const min = new BN('1234');
  8. const max = new BN('5678');
  9. const MAX_UINT256_SUB1 = MAX_UINT256.sub(new BN('1'));
  10. const MAX_UINT256_SUB2 = MAX_UINT256.sub(new BN('2'));
  11. beforeEach(async function () {
  12. this.math = await MathMock.new();
  13. });
  14. describe('max', function () {
  15. it('is correctly detected in first argument position', async function () {
  16. expect(await this.math.max(max, min)).to.be.bignumber.equal(max);
  17. });
  18. it('is correctly detected in second argument position', async function () {
  19. expect(await this.math.max(min, max)).to.be.bignumber.equal(max);
  20. });
  21. });
  22. describe('min', function () {
  23. it('is correctly detected in first argument position', async function () {
  24. expect(await this.math.min(min, max)).to.be.bignumber.equal(min);
  25. });
  26. it('is correctly detected in second argument position', async function () {
  27. expect(await this.math.min(max, min)).to.be.bignumber.equal(min);
  28. });
  29. });
  30. describe('average', function () {
  31. function bnAverage (a, b) {
  32. return a.add(b).divn(2);
  33. }
  34. it('is correctly calculated with two odd numbers', async function () {
  35. const a = new BN('57417');
  36. const b = new BN('95431');
  37. expect(await this.math.average(a, b)).to.be.bignumber.equal(bnAverage(a, b));
  38. });
  39. it('is correctly calculated with two even numbers', async function () {
  40. const a = new BN('42304');
  41. const b = new BN('84346');
  42. expect(await this.math.average(a, b)).to.be.bignumber.equal(bnAverage(a, b));
  43. });
  44. it('is correctly calculated with one even and one odd number', async function () {
  45. const a = new BN('57417');
  46. const b = new BN('84346');
  47. expect(await this.math.average(a, b)).to.be.bignumber.equal(bnAverage(a, b));
  48. });
  49. it('is correctly calculated with two max uint256 numbers', async function () {
  50. const a = MAX_UINT256;
  51. expect(await this.math.average(a, a)).to.be.bignumber.equal(bnAverage(a, a));
  52. });
  53. });
  54. describe('ceilDiv', function () {
  55. it('does not round up on exact division', async function () {
  56. const a = new BN('10');
  57. const b = new BN('5');
  58. expect(await this.math.ceilDiv(a, b)).to.be.bignumber.equal('2');
  59. });
  60. it('rounds up on division with remainders', async function () {
  61. const a = new BN('42');
  62. const b = new BN('13');
  63. expect(await this.math.ceilDiv(a, b)).to.be.bignumber.equal('4');
  64. });
  65. it('does not overflow', async function () {
  66. const b = new BN('2');
  67. const result = new BN('1').shln(255);
  68. expect(await this.math.ceilDiv(MAX_UINT256, b)).to.be.bignumber.equal(result);
  69. });
  70. it('correctly computes max uint256 divided by 1', async function () {
  71. const b = new BN('1');
  72. expect(await this.math.ceilDiv(MAX_UINT256, b)).to.be.bignumber.equal(MAX_UINT256);
  73. });
  74. });
  75. describe('muldiv', function () {
  76. it('divide by 0', async function () {
  77. await expectRevert.unspecified(this.math.mulDiv(1, 1, 0, Rounding.Down));
  78. });
  79. describe('does round down', async function () {
  80. it('small values', async function () {
  81. expect(await this.math.mulDiv('3', '4', '5', Rounding.Down)).to.be.bignumber.equal('2');
  82. expect(await this.math.mulDiv('3', '5', '5', Rounding.Down)).to.be.bignumber.equal('3');
  83. });
  84. it('large values', async function () {
  85. expect(await this.math.mulDiv(
  86. new BN('42'),
  87. MAX_UINT256_SUB1,
  88. MAX_UINT256,
  89. Rounding.Down,
  90. )).to.be.bignumber.equal(new BN('41'));
  91. expect(await this.math.mulDiv(
  92. new BN('17'),
  93. MAX_UINT256,
  94. MAX_UINT256,
  95. Rounding.Down,
  96. )).to.be.bignumber.equal(new BN('17'));
  97. expect(await this.math.mulDiv(
  98. MAX_UINT256_SUB1,
  99. MAX_UINT256_SUB1,
  100. MAX_UINT256,
  101. Rounding.Down,
  102. )).to.be.bignumber.equal(MAX_UINT256_SUB2);
  103. expect(await this.math.mulDiv(
  104. MAX_UINT256,
  105. MAX_UINT256_SUB1,
  106. MAX_UINT256,
  107. Rounding.Down,
  108. )).to.be.bignumber.equal(MAX_UINT256_SUB1);
  109. expect(await this.math.mulDiv(
  110. MAX_UINT256,
  111. MAX_UINT256,
  112. MAX_UINT256,
  113. Rounding.Down,
  114. )).to.be.bignumber.equal(MAX_UINT256);
  115. });
  116. });
  117. describe('does round up', async function () {
  118. it('small values', async function () {
  119. expect(await this.math.mulDiv('3', '4', '5', Rounding.Up)).to.be.bignumber.equal('3');
  120. expect(await this.math.mulDiv('3', '5', '5', Rounding.Up)).to.be.bignumber.equal('3');
  121. });
  122. it('large values', async function () {
  123. expect(await this.math.mulDiv(
  124. new BN('42'),
  125. MAX_UINT256_SUB1,
  126. MAX_UINT256,
  127. Rounding.Up,
  128. )).to.be.bignumber.equal(new BN('42'));
  129. expect(await this.math.mulDiv(
  130. new BN('17'),
  131. MAX_UINT256,
  132. MAX_UINT256,
  133. Rounding.Up,
  134. )).to.be.bignumber.equal(new BN('17'));
  135. expect(await this.math.mulDiv(
  136. MAX_UINT256_SUB1,
  137. MAX_UINT256_SUB1,
  138. MAX_UINT256,
  139. Rounding.Up,
  140. )).to.be.bignumber.equal(MAX_UINT256_SUB1);
  141. expect(await this.math.mulDiv(
  142. MAX_UINT256,
  143. MAX_UINT256_SUB1,
  144. MAX_UINT256,
  145. Rounding.Up,
  146. )).to.be.bignumber.equal(MAX_UINT256_SUB1);
  147. expect(await this.math.mulDiv(
  148. MAX_UINT256,
  149. MAX_UINT256,
  150. MAX_UINT256,
  151. Rounding.Up,
  152. )).to.be.bignumber.equal(MAX_UINT256);
  153. });
  154. });
  155. });
  156. });