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 });