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