/ test / BancorFormula_spec.js
BancorFormula_spec.js
  1  /*global contract, config, it, assert, embark, web3, before, describe, beforeEach*/
  2  const BigNumber = require('bignumber.js');
  3  const constants = require('../utils/FormulaConstants.js');
  4  const catchRevert = require("../utils/Utils").catchRevert;
  5  const TestBancorFormula = require('Embark/contracts/TestBancorFormula');
  6  
  7  config({
  8    blockchain: {
  9      accounts: [
 10        {
 11          mnemonic: 'foster gesture flock merge beach plate dish view friend leave drink valley shield list enemy',
 12          balance: '5 ether',
 13          numAddresses: '10',
 14        },
 15      ],
 16    },
 17    contracts: {
 18      deploy: {
 19        'TestBancorFormula': {},
 20      },
 21    },
 22  }, (_err, web3_accounts) => {
 23    accounts = web3_accounts
 24  })
 25  
 26  contract('TestBancorFormula', function () {
 27      let ILLEGAL_VAL = new BigNumber(2).exponentiatedBy(256);
 28      let MAX_BASE_N = new BigNumber(2).exponentiatedBy(256 - constants.MAX_PRECISION).minus(1);
 29      let MIN_BASE_D = new BigNumber(1);
 30      let MAX_EXPONENT = 1000000;
 31  
 32      for (let percent = 1; percent <= 100; percent++) {
 33          let baseN = web3.utils.toHex(MAX_BASE_N);
 34          let baseD = web3.utils.toHex(MAX_BASE_N.minus(1));
 35          let expN  = MAX_EXPONENT * percent / 100;
 36          let expD  = MAX_EXPONENT;
 37          let test  = `Function power(0x${baseN.toString(16)}, 0x${baseD.toString(16)}, ${expN}, ${expD})`;
 38  
 39          it(`${test}:`, async () => {
 40              await TestBancorFormula.methods.powerTest(baseN, baseD, expN, expD).call();
 41          });
 42      }
 43  
 44      for (let percent = 1; percent <= 100; percent++) {
 45          let baseN = web3.utils.toHex(MAX_BASE_N);
 46          let baseD = web3.utils.toHex(MAX_BASE_N.minus(1));
 47          let expN  = MAX_EXPONENT;
 48          let expD  = MAX_EXPONENT * percent / 100;
 49          let test  = `Function power(0x${baseN.toString(16)}, 0x${baseD.toString(16)}, ${expN}, ${expD})`;
 50  
 51          it(`${test}:`, async () => {
 52              await TestBancorFormula.methods.powerTest(baseN, baseD, expN, expD).call();
 53          });
 54      }
 55  
 56      for (let percent = 1; percent <= 100; percent++) {
 57          let baseN = web3.utils.toHex(MAX_BASE_N);
 58          let baseD = web3.utils.toHex((MIN_BASE_D));
 59          let expN  = MAX_EXPONENT * percent / 100;
 60          let expD  = MAX_EXPONENT;
 61          let test  = `Function power(0x${baseN.toString(16)}, 0x${baseD.toString(16)}, ${expN}, ${expD})`;
 62  
 63          it(`${test}:`, async () => {
 64              if (percent < 64)
 65                  await TestBancorFormula.methods.powerTest(baseN, baseD, expN, expD).call();
 66              else
 67                  await catchRevert(TestBancorFormula.methods.powerTest(baseN, baseD, expN, expD).call());
 68          });
 69      }
 70  
 71      for (let percent = 1; percent <= 100; percent++) {
 72          let baseN = web3.utils.toHex(MAX_BASE_N);
 73          let baseD = web3.utils.toHex(MIN_BASE_D);
 74          let expN  = MAX_EXPONENT;
 75          let expD  = MAX_EXPONENT * percent / 100;
 76          let test  = `Function power(0x${baseN.toString(16)}, 0x${baseD.toString(16)}, ${expN}, ${expD})`;
 77  
 78          it(`${test}:`, async () => {
 79              await catchRevert(TestBancorFormula.methods.powerTest(baseN, baseD, expN, expD).call());
 80          });
 81      }
 82  
 83      let values = [
 84          MAX_BASE_N.dividedBy(MIN_BASE_D).integerValue(),
 85          MAX_BASE_N.dividedBy(MAX_BASE_N.minus(1)).integerValue(),
 86          MIN_BASE_D.plus(1).dividedBy(MIN_BASE_D).integerValue(),
 87      ];
 88  
 89      for (let index = 0; index < values.length; index++) {
 90          let test = `Function generalLog(0x${values[index].toString(16)})`;
 91  
 92          it(`${test}:`, async () => {
 93              try {
 94                  let temp = web3.utils.toHex(values[index]);
 95                  let retVal = await TestBancorFormula.methods.generalLogTest(temp).call();
 96                  let check = new BigNumber(parseInt(retVal, 10) * MAX_EXPONENT);
 97                  assert(check.isLessThan(ILLEGAL_VAL), `${test}: output is too large`);
 98              }
 99              catch (error) {
100                  assert(false, error.message);
101              }
102          });
103      }
104  
105      for (let precision = constants.MIN_PRECISION; precision <= constants.MAX_PRECISION; precision++) {
106          let maxExp = new BigNumber(constants.maxExpArray[precision]);
107          let shlVal = new BigNumber(2).exponentiatedBy(constants.MAX_PRECISION - precision);
108          let tuples = [
109              {'input' : maxExp.plus(0).times(shlVal).minus(1), 'output' : new BigNumber(precision-0)},
110              {'input' : maxExp.plus(0).times(shlVal).minus(0), 'output' : new BigNumber(precision-0)},
111              {'input' : maxExp.plus(1).times(shlVal).minus(1), 'output' : new BigNumber(precision-0)},
112              {'input' : maxExp.plus(1).times(shlVal).minus(0), 'output' : new BigNumber(precision-1)},
113          ];
114  
115          for (let index = 0; index < tuples.length; index++) {
116              let input  = web3.utils.toHex(tuples[index]['input' ]);
117              let output = tuples[index]['output'];
118              let test   = `Function findPositionInMaxExpArray(0x${input.toString(16)})`;
119  
120              it(`${test}:`, async () => {
121                  if (precision == constants.MIN_PRECISION && output.isLessThan(BigNumber(precision))) {
122                      await catchRevert(TestBancorFormula.methods.findPositionInMaxExpArrayTest(input).call());
123                  }
124                  else {
125                      let temp = await TestBancorFormula.methods.findPositionInMaxExpArrayTest(input).call();
126                      let retVal = new BigNumber(temp);
127                      assert(retVal.isEqualTo(output), `${test}: output should be ${output.toString(10)} but it is ${retVal.toString(10)}`);
128                  }
129              });
130          }
131      }
132  
133      for (let precision = constants.MIN_PRECISION; precision <= constants.MAX_PRECISION; precision++) {
134          let maxExp = new BigNumber(constants.maxExpArray[precision]);
135          let maxVal = new BigNumber(constants.maxValArray[precision]);
136          let errExp = maxExp.plus(1);
137          let maxExpi = web3.utils.toHex(maxExp);
138          let errExpi = web3.utils.toHex(errExp);
139          let test1  = `Function generalExp(0x${maxExp.toString(16)}, ${precision})`;
140          let test2  = `Function generalExp(0x${errExp.toString(16)}, ${precision})`;
141  
142          it(`${test1}:`, async () => {
143              let temp = await TestBancorFormula.methods.generalExpTest(maxExpi, precision).call();
144              let retVal = new BigNumber(temp);
145              assert(retVal.isEqualTo(maxVal), `${test1}: output is wrong`);
146          });
147  
148          it(`${test2}:`, async () => {
149              let temp = await TestBancorFormula.methods.generalExpTest(errExpi, precision).call();
150              let retVal = new BigNumber(temp);
151              assert(retVal.isLessThan(maxVal), `${test2}:  output indicates that maxExpArray[${precision}] is wrong`);
152          });
153      }
154  
155      for (let precision = constants.MIN_PRECISION; precision <= constants.MAX_PRECISION; precision++) {
156          let minExp = new BigNumber(constants.maxExpArray[precision-1]).plus(1);
157          let minVal = new BigNumber(2).exponentiatedBy(precision);
158          let minExpi = web3.utils.toHex(minExp);
159          let test   = `Function generalExp(0x${minExp.toString(16)}, ${precision})`;
160  
161          it(`${test}:`, async () => {
162              let temp = await TestBancorFormula.methods.generalExpTest(minExpi, precision).call();
163              let retVal = new BigNumber(temp);
164              assert(retVal.isGreaterThanOrEqualTo(minVal), `${test}: output is too small`);
165          });
166      }
167  
168      for (let n = 1; n <= 255; n++) {
169          let tuples = [
170              {'input' : new BigNumber(2).exponentiatedBy(n)           , 'output' : new BigNumber(n)},
171              {'input' : new BigNumber(2).exponentiatedBy(n).plus(1)   , 'output' : new BigNumber(n)},
172              {'input' : new BigNumber(2).exponentiatedBy(n+1).minus(1), 'output' : new BigNumber(n)},
173          ];
174  
175          for (let index = 0; index < tuples.length; index++) {
176              let input  = web3.utils.toHex(tuples[index]['input' ]);
177              let output = tuples[index]['output'];
178              let test   = `Function floorLog2(0x${input.toString(16)})`;
179  
180              it(`${test}:`, async () => {
181                  let temp = await TestBancorFormula.methods.floorLog2Test(input).call();
182                  let retVal = new BigNumber(temp);
183                  assert(retVal.isEqualTo(output), `${test}: output should be ${output.toString(10)} but it is ${retVal.toString(10)}`);
184              });
185          }
186      }
187  
188      let Decimal = require("decimal.js");
189      Decimal.set({precision: 100, rounding: Decimal.ROUND_DOWN});
190      BigNumber.config({DECIMAL_PLACES: 100, ROUNDING_MODE: BigNumber.ROUND_DOWN});
191  
192      let LOG_MIN = 1;
193      let EXP_MIN = 0;
194      let LOG_MAX = new BigNumber(Decimal.exp(1).toFixed());
195      let EXP_MAX = new BigNumber(Decimal.pow(2,4).toFixed());
196      let FIXED_1 = new BigNumber(2).exponentiatedBy(constants.MAX_PRECISION);
197  
198      for (let percent = 0; percent < 100; percent++) {
199          let x = new BigNumber(percent).dividedBy(100).times(LOG_MAX.minus(LOG_MIN)).plus(LOG_MIN);
200  
201          it(`Function optimalLog(${x.toFixed()})`, async () => {
202              try {
203                  let tmp = web3.utils.toHex(FIXED_1.times(x).integerValue());
204                  let temp = await TestBancorFormula.methods.optimalLogTest(tmp).call();
205                  let fixedPoint = new BigNumber(temp);
206                  let floatPoint = new BigNumber(Decimal(x.toFixed()).ln().times(FIXED_1.toFixed()).toFixed());
207                  let ratio = fixedPoint.isEqualTo(floatPoint) ? BigNumber(1) : fixedPoint.dividedBy(floatPoint);
208                  assert(ratio.isGreaterThanOrEqualTo("0.99999999999999999999999999999999999") && ratio.isLessThanOrEqualTo("1"), `ratio = ${ratio.toFixed()}`);
209              }
210              catch (error) {
211                  assert(false, error.message);
212              }
213          });
214      }
215  
216      for (let percent = 0; percent < 100; percent++) {
217          let x = new BigNumber(percent).dividedBy(100).times(EXP_MAX.minus(EXP_MIN)).plus(EXP_MIN);
218  
219          it(`Function optimalExp(${x.toFixed()})`, async () => {
220              try {
221                  let tmp = web3.utils.toHex(FIXED_1.times(x).integerValue());
222                  let temp = await TestBancorFormula.methods.optimalExpTest(tmp).call();
223                  let fixedPoint = new BigNumber(temp);
224                  let floatPoint = new BigNumber(Decimal(x.toFixed()).exp().times(FIXED_1.toFixed()).toFixed());
225                  let ratio = fixedPoint.isEqualTo(floatPoint) ? new BigNumber(1) : fixedPoint.dividedBy(floatPoint);
226                  assert(ratio.isGreaterThanOrEqualTo("0.99999999999999999999999999999999999") && ratio.isLessThanOrEqualTo("1"), `ratio = ${ratio.toFixed()}`);
227              }
228              catch (error) {
229                  assert(false, error.message);
230              }
231          });
232      }
233  
234      for (let n = 0; n < 256 - constants.MAX_PRECISION; n++) {
235          let values = [
236              new BigNumber(2).exponentiatedBy(n),
237              new BigNumber(2).exponentiatedBy(n).plus(1),
238              new BigNumber(2).exponentiatedBy(n).times(1.5),
239              new BigNumber(2).exponentiatedBy(n+1).minus(1),
240          ];
241  
242          for (let index = 0; index < values.length; index++) {
243              let x = values[index];
244  
245              it(`Function generalLog(${x.toFixed()})`, async () => {
246                  try {
247                      let tmp = web3.utils.toHex(FIXED_1.times(x).integerValue());
248                      let temp = await TestBancorFormula.methods.generalLogTest(tmp).call();
249                      let fixedPoint = new BigNumber(temp);
250                      let floatPoint = new BigNumber(Decimal(x.toFixed()).ln().times(FIXED_1.toFixed()).toFixed());
251                      let ratio = fixedPoint.isEqualTo(floatPoint) ? new BigNumber(1) : fixedPoint.dividedBy(floatPoint);
252                      assert(ratio.isGreaterThanOrEqualTo("0.99999999999999999999999999999999999") && ratio.isLessThanOrEqualTo("1"), `ratio = ${ratio.toFixed()}`);
253                  }
254                  catch (error) {
255                      assert(false, error.message);
256                  }
257              });
258          }
259      }
260  });