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