diff --git a/.gitignore b/.gitignore index 219383ac..245abc66 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,4 @@ coverage.json .env -deployment \ No newline at end of file +deployment/script-hardhat.json \ No newline at end of file diff --git a/contracts/curves/BancorZeroCurve.sol b/contracts/curves/BancorZeroCurve.sol index 33eaee3e..c2bf1812 100644 --- a/contracts/curves/BancorZeroCurve.sol +++ b/contracts/curves/BancorZeroCurve.sol @@ -7,16 +7,19 @@ import "../interfaces/ICurveRegistry.sol"; import "../libs/WeightedAverage.sol"; import "../libs/Details.sol"; -import "../utils/Power.sol"; import "../utils/ABDKMathQuad.sol"; /// @title Bancor curve registry and calculator /// @author Carl Farterson (@carlfarterson) -contract BancorZeroCurve is ICurve, Power { +contract BancorZeroCurve is ICurve { using ABDKMathQuad for uint256; using ABDKMathQuad for bytes16; - bytes16 private immutable _one = (uint256(1 ether)).fromUInt(); + bytes16 private immutable _baseX = uint256(1 ether).fromUInt(); + // uint256 public BASE_X = uint256(1 ether); + uint32 public maxWeight = 1000000; + bytes16 private immutable _one = (uint256(1)).fromUInt(); + // NOTE: keys are their respective hubId mapping(uint256 => Details.BancorDetails) private _bancors; @@ -31,12 +34,9 @@ contract BancorZeroCurve is ICurve, Power { _encodedValueSet, (uint256, uint32) ); + require(baseY > 0, "baseY not in range"); require( - baseY > 0 && baseY <= PRECISION * PRECISION, - "baseY not in range" - ); - require( - reserveWeight > 0 && reserveWeight <= MAX_WEIGHT, + reserveWeight > 0 && reserveWeight <= maxWeight, "reserveWeight not in range" ); @@ -52,12 +52,9 @@ contract BancorZeroCurve is ICurve, Power { // TODO: access control uint32 targetReserveWeight = abi.decode(_encodedValueSet, (uint32)); - Details.BancorDetails storage bancorDetails = _bancors[_hubId]; - require( - targetReserveWeight > 0 && targetReserveWeight <= MAX_WEIGHT, - "reserveWeight not in range" - ); + + require(targetReserveWeight > 0, "reserveWeight not in range"); require( targetReserveWeight != bancorDetails.reserveWeight, "targeReserveWeight == reserveWeight" @@ -107,7 +104,6 @@ contract BancorZeroCurve is ICurve, Power { meTokensReturned = _calculateMintReturnFromZero( _tokensDeposited, bancorDetails.reserveWeight, - BASE_X, bancorDetails.baseY ); } @@ -132,7 +128,6 @@ contract BancorZeroCurve is ICurve, Power { meTokensReturned = _calculateMintReturnFromZero( _tokensDeposited, bancorDetails.targetReserveWeight, - BASE_X, bancorDetails.targetBaseY ); } @@ -187,70 +182,55 @@ contract BancorZeroCurve is ICurve, Power { require( _balancePooled > 0 && _reserveWeight > 0 && - _reserveWeight <= MAX_WEIGHT + _reserveWeight <= maxWeight ); // special case for 0 deposit amount if (_tokensDeposited == 0) { return 0; } // special case if the weight = 100% - if (_reserveWeight == MAX_WEIGHT) { + if (_reserveWeight == maxWeight) { return (_supply * _tokensDeposited) / _balancePooled; } - uint8 precision; - uint256 result; - uint256 baseN = _tokensDeposited + _balancePooled; - (result, precision) = power( - baseN, - _balancePooled, - _reserveWeight, - MAX_WEIGHT + bytes16 exponent = uint256(_reserveWeight).fromUInt().div( + uint256(maxWeight).fromUInt() + ); + bytes16 part1 = _one.add( + _tokensDeposited.fromUInt().div(_balancePooled.fromUInt()) + ); + //Instead of calculating "base ^ exp", we calculate "e ^ (log(base) * exp)". + bytes16 res = _supply.fromUInt().mul( + (part1.ln().mul(exponent)).exp().sub(_one) ); - uint256 newTokenSupply = (_supply * result) >> precision; - return newTokenSupply - _supply; + return res.toUInt(); } /// @notice Given a deposit (in the collateral token) meToken supply of 0, constant x and /// constant y, calculates the return for a given conversion (in the meToken) - /// @dev _baseX and _baseY are needed as Bancor formula breaks from a divide-by-0 when supply=0 + /// @dev _baseX / (_baseY ^ (MAX_WEIGHT/reserveWeight -1)) * tokensDeposited ^(MAX_WEIGHT/reserveWeight -1) + /// @dev _baseX and _baseY are needed as Bancor formula breaks from a divide-by-0 when supply=0 /// @param _tokensDeposited amount of collateral tokens to deposit - /// @param _baseX constant X /// @param _baseY constant y /// @return amount of meTokens minted function _calculateMintReturnFromZero( uint256 _tokensDeposited, uint256 _reserveWeight, - uint256 _baseX, uint256 _baseY ) private view returns (uint256) { - bytes16 y = _baseY.fromUInt(); - bytes16 max = uint256(MAX_WEIGHT).fromUInt(); // shares amount - bytes16 s = _tokensDeposited.fromUInt(); - bytes16 r = _reserveWeight.fromUInt(); - bytes16 x = _baseX.fromUInt(); - bytes16 exponent = max.div(r).sub(uint256(1).fromUInt()); - //uint256 exponent = ((MAX_WEIGHT / _reserveWeight) - 1); + // (MAX_WEIGHT/reserveWeight -1) + bytes16 exponent = uint256(maxWeight) + .fromUInt() + .div(_reserveWeight.fromUInt()) + .sub(_one); // Instead of calculating "x ^ exp", we calculate "e ^ (log(x) * exp)". - bytes16 denominator = (y.ln().mul(exponent)).exp(); - // bytes16 denominator = x.pow(exponent.toUInt()); - // Instead of calculating "s ^ exp", we calculate "e ^ (log(s) * exp)". - bytes16 res1 = x.mul(s.ln().mul(exponent).exp()); - // bytes16 res1 = numerator.mul(s.pow(exponent.toUInt())); - bytes16 res2 = res1.div(denominator); - return res2.toUInt(); - /* //uint256 exponent = ((MAX_WEIGHT / _reserveWeight) - 1); - console.log("## exponent:%s", exponent.mul(_one).toUInt()); - // Instead of calculating "x ^ exp", we calculate "e ^ (log(x) * exp)". - bytes16 denominator = (x.ln().mul(exponent)).exp(); - // bytes16 denominator = x.pow(exponent.toUInt()); - console.log("## denominator:%s", denominator.toUInt()); - // Instead of calculating "s ^ exp", we calculate "e ^ (log(s) * exp)". - bytes16 res1 = numerator.mul(s.ln().mul(exponent).exp()); - // bytes16 res1 = numerator.mul(s.pow(exponent.toUInt())); - bytes16 res2 = res1.div(denominator); - return res2.toUInt(); */ - // return (numerator * _tokensDeposited**exponent) / denominator; + // _baseY ^ (MAX_WEIGHT/reserveWeight -1) + bytes16 denominator = (_baseY.fromUInt().ln().mul(exponent)).exp(); + // ( baseX * tokensDeposited ^ (MAX_WEIGHT/reserveWeight -1) ) / _baseY ^ (MAX_WEIGHT/reserveWeight -1) + bytes16 res = _baseX + .mul(_tokensDeposited.fromUInt().ln().mul(exponent).exp()) + .div(denominator); + return res.toUInt(); } /// @notice Given an amount of meTokens to burn, connector weight, supply and collateral pooled, @@ -272,7 +252,7 @@ contract BancorZeroCurve is ICurve, Power { _supply > 0 && _balancePooled > 0 && _reserveWeight > 0 && - _reserveWeight <= MAX_WEIGHT && + _reserveWeight <= maxWeight && _meTokensBurned <= _supply ); // special case for 0 sell amount @@ -284,17 +264,24 @@ contract BancorZeroCurve is ICurve, Power { return _balancePooled; } // special case if the weight = 100% - if (_reserveWeight == MAX_WEIGHT) { + if (_reserveWeight == maxWeight) { return (_balancePooled * _meTokensBurned) / _supply; } - - uint256 result; - uint8 precision; - uint256 baseD = _supply - _meTokensBurned; - (result, precision) = power(_supply, baseD, MAX_WEIGHT, _reserveWeight); - uint256 oldBalance = _balancePooled * result; - uint256 newBalance = _balancePooled << precision; - - return (oldBalance - newBalance) / result; + // 1 / (reserveWeight/MAX_WEIGHT) + bytes16 exponent = _one.div( + uint256(_reserveWeight).fromUInt().div( + uint256(maxWeight).fromUInt() + ) + ); + // 1 - (meTokensBurned / supply) + bytes16 s = _one.sub( + _meTokensBurned.fromUInt().div(_supply.fromUInt()) + ); + // Instead of calculating "s ^ exp", we calculate "e ^ (log(s) * exp)". + // balancePooled - ( balancePooled * s ^ exp)) + bytes16 res = _balancePooled.fromUInt().sub( + _balancePooled.fromUInt().mul(s.ln().mul(exponent).exp()) + ); + return res.toUInt(); } } diff --git a/contracts/factories/vaults/SingleAssetFactory.sol b/contracts/factories/vaults/SingleAssetFactory.sol index 63c7674a..e5f574ec 100644 --- a/contracts/factories/vaults/SingleAssetFactory.sol +++ b/contracts/factories/vaults/SingleAssetFactory.sol @@ -7,8 +7,6 @@ import "../../vaults/SingleAssetVault.sol"; import "../../interfaces/IVaultRegistry.sol"; import "../../interfaces/IVaultFactory.sol"; -import "hardhat/console.sol"; - // TODO: Should IHub be imported? /// @title Factory contract to erc20-collateral vaults diff --git a/contracts/mock/PowerMock.sol b/contracts/mock/PowerMock.sol deleted file mode 100644 index 56a03644..00000000 --- a/contracts/mock/PowerMock.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.0; -import "../utils/Power.sol"; - -/* - BancorFormula test helper that exposes some BancorFormula functions -*/ -contract PowerMock is Power { - function findPositionInMaxExpArrayTest(uint256 _x) - public - view - returns (uint8) - { - return findPositionInMaxExpArray(_x); - } - - function generalExpTest(uint256 _x, uint8 _precision) - public - pure - returns (uint256) - { - return generalExp(_x, _precision); - } - - function floorLog2Test(uint256 _n) public pure returns (uint8) { - return floorLog2(_n); - } -} diff --git a/contracts/utils/Power.sol b/contracts/utils/Power.sol deleted file mode 100644 index 5516d623..00000000 --- a/contracts/utils/Power.sol +++ /dev/null @@ -1,516 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity ^0.8.0; - -/// @title Power function by Bancor -/// @dev https://github.com/bancorprotocol/contracts -/// @notice Modified from the original by Slava Balasanov & Tarrence van As -abstract contract Power { - uint256 public PRECISION = 10**18; - uint256 public BASE_X = PRECISION; - uint32 public MAX_WEIGHT = 1000000; - - uint256 private constant ONE = 1; - uint8 private constant MIN_PRECISION = 32; - uint8 private constant MAX_PRECISION = 127; - - // The values below depend on MAX_PRECISION. If you choose to change it: - // Apply the same change in file 'PrintIntScalingFactors.py', run it and paste the results below. - uint256 private constant FIXED_1 = 0x080000000000000000000000000000000; - uint256 private constant FIXED_2 = 0x100000000000000000000000000000000; - uint256 private constant MAX_NUM = 0x200000000000000000000000000000000; - - // Auto-generated via 'PrintLn2ScalingFactors.py' - uint256 private constant LN2_NUMERATOR = 0x3f80fe03f80fe03f80fe03f80fe03f8; - uint256 private constant LN2_DENOMINATOR = - 0x5b9de1d10bf4103d647b0955897ba80; - - // Auto-generated via 'PrintFunctionOptimalLog.py' and 'PrintFunctionOptimalExp.py' - uint256 private constant OPT_LOG_MAX_VAL = - 0x15bf0a8b1457695355fb8ac404e7a79e3; - uint256 private constant OPT_EXP_MAX_VAL = - 0x800000000000000000000000000000000; - - // The values below depend on MIN_PRECISION and MAX_PRECISION. If you choose to change either one of them: - // Apply the same change in file 'PrintFunctionBancorFormula.py', run it and paste the results below. - uint256[128] private maxExpArray; - - constructor() { - maxExpArray[32] = 0x1c35fedd14ffffffffffffffffffffffff; - maxExpArray[33] = 0x1b0ce43b323fffffffffffffffffffffff; - maxExpArray[34] = 0x19f0028ec1ffffffffffffffffffffffff; - maxExpArray[35] = 0x18ded91f0e7fffffffffffffffffffffff; - maxExpArray[36] = 0x17d8ec7f0417ffffffffffffffffffffff; - maxExpArray[37] = 0x16ddc6556cdbffffffffffffffffffffff; - maxExpArray[38] = 0x15ecf52776a1ffffffffffffffffffffff; - maxExpArray[39] = 0x15060c256cb2ffffffffffffffffffffff; - maxExpArray[40] = 0x1428a2f98d72ffffffffffffffffffffff; - maxExpArray[41] = 0x13545598e5c23fffffffffffffffffffff; - maxExpArray[42] = 0x1288c4161ce1dfffffffffffffffffffff; - maxExpArray[43] = 0x11c592761c666fffffffffffffffffffff; - maxExpArray[44] = 0x110a688680a757ffffffffffffffffffff; - maxExpArray[45] = 0x1056f1b5bedf77ffffffffffffffffffff; - maxExpArray[46] = 0x0faadceceeff8bffffffffffffffffffff; - maxExpArray[47] = 0x0f05dc6b27edadffffffffffffffffffff; - maxExpArray[48] = 0x0e67a5a25da4107fffffffffffffffffff; - maxExpArray[49] = 0x0dcff115b14eedffffffffffffffffffff; - maxExpArray[50] = 0x0d3e7a392431239fffffffffffffffffff; - maxExpArray[51] = 0x0cb2ff529eb71e4fffffffffffffffffff; - maxExpArray[52] = 0x0c2d415c3db974afffffffffffffffffff; - maxExpArray[53] = 0x0bad03e7d883f69bffffffffffffffffff; - maxExpArray[54] = 0x0b320d03b2c343d5ffffffffffffffffff; - maxExpArray[55] = 0x0abc25204e02828dffffffffffffffffff; - maxExpArray[56] = 0x0a4b16f74ee4bb207fffffffffffffffff; - maxExpArray[57] = 0x09deaf736ac1f569ffffffffffffffffff; - maxExpArray[58] = 0x0976bd9952c7aa957fffffffffffffffff; - maxExpArray[59] = 0x09131271922eaa606fffffffffffffffff; - maxExpArray[60] = 0x08b380f3558668c46fffffffffffffffff; - maxExpArray[61] = 0x0857ddf0117efa215bffffffffffffffff; - maxExpArray[62] = 0x07ffffffffffffffffffffffffffffffff; - maxExpArray[63] = 0x07abbf6f6abb9d087fffffffffffffffff; - maxExpArray[64] = 0x075af62cbac95f7dfa7fffffffffffffff; - maxExpArray[65] = 0x070d7fb7452e187ac13fffffffffffffff; - maxExpArray[66] = 0x06c3390ecc8af379295fffffffffffffff; - maxExpArray[67] = 0x067c00a3b07ffc01fd6fffffffffffffff; - maxExpArray[68] = 0x0637b647c39cbb9d3d27ffffffffffffff; - maxExpArray[69] = 0x05f63b1fc104dbd39587ffffffffffffff; - maxExpArray[70] = 0x05b771955b36e12f7235ffffffffffffff; - maxExpArray[71] = 0x057b3d49dda84556d6f6ffffffffffffff; - maxExpArray[72] = 0x054183095b2c8ececf30ffffffffffffff; - maxExpArray[73] = 0x050a28be635ca2b888f77fffffffffffff; - maxExpArray[74] = 0x04d5156639708c9db33c3fffffffffffff; - maxExpArray[75] = 0x04a23105873875bd52dfdfffffffffffff; - maxExpArray[76] = 0x0471649d87199aa990756fffffffffffff; - maxExpArray[77] = 0x04429a21a029d4c1457cfbffffffffffff; - maxExpArray[78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff; - maxExpArray[79] = 0x03eab73b3bbfe282243ce1ffffffffffff; - maxExpArray[80] = 0x03c1771ac9fb6b4c18e229ffffffffffff; - maxExpArray[81] = 0x0399e96897690418f785257fffffffffff; - maxExpArray[82] = 0x0373fc456c53bb779bf0ea9fffffffffff; - maxExpArray[83] = 0x034f9e8e490c48e67e6ab8bfffffffffff; - maxExpArray[84] = 0x032cbfd4a7adc790560b3337ffffffffff; - maxExpArray[85] = 0x030b50570f6e5d2acca94613ffffffffff; - maxExpArray[86] = 0x02eb40f9f620fda6b56c2861ffffffffff; - maxExpArray[87] = 0x02cc8340ecb0d0f520a6af58ffffffffff; - maxExpArray[88] = 0x02af09481380a0a35cf1ba02ffffffffff; - maxExpArray[89] = 0x0292c5bdd3b92ec810287b1b3fffffffff; - maxExpArray[90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff; - maxExpArray[91] = 0x025daf6654b1eaa55fd64df5efffffffff; - maxExpArray[92] = 0x0244c49c648baa98192dce88b7ffffffff; - maxExpArray[93] = 0x022ce03cd5619a311b2471268bffffffff; - maxExpArray[94] = 0x0215f77c045fbe885654a44a0fffffffff; - maxExpArray[95] = 0x01ffffffffffffffffffffffffffffffff; - maxExpArray[96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff; - maxExpArray[97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff; - maxExpArray[98] = 0x01c35fedd14b861eb0443f7f133fffffff; - maxExpArray[99] = 0x01b0ce43b322bcde4a56e8ada5afffffff; - maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff; - maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff; - maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff; - maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff; - maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff; - maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff; - maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff; - maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff; - maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff; - maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff; - maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff; - maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff; - maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff; - maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff; - maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff; - maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff; - maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff; - maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff; - maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff; - maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff; - maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff; - maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf; - maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df; - maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f; - maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037; - maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf; - maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9; - maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6; - } - - /** - General Description: - Determine a value of precision. - Calculate an integer approximation of (_baseN / _baseD) ^ (_expN / _expD) * 2 ^ precision. - Return the result along with the precision used. - Detailed Description: - Instead of calculating "base ^ exp", we calculate "e ^ (log(base) * exp)". - The value of "log(base)" is represented with an integer slightly smaller than "log(base) * 2 ^ precision". - The larger "precision" is, the more accurately this value represents the real value. - However, the larger "precision" is, the more bits are required in order to store this value. - And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (maximum value of "x"). - This maximum exponent depends on the "precision" used, and it is given by "maxExpArray[precision] >> (MAX_PRECISION - precision)". - Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function. - This allows us to compute "base ^ exp" with maximum accuracy and without exceeding 256 bits in any of the intermediate computations. - This functions assumes that "_expN < 2 ^ 256 / log(MAX_NUM - 1)", otherwise the multiplication should be replaced with a "safeMul". - */ - function power( - uint256 _baseN, - uint256 _baseD, - uint32 _expN, - uint32 _expD - ) internal view returns (uint256, uint8) { - assert(_baseN < MAX_NUM); - require(_baseN >= _baseD, "Bases < 1 are not supported."); - - uint256 baseLog; - uint256 base = (_baseN * FIXED_1) / _baseD; - if (base < OPT_LOG_MAX_VAL) { - baseLog = optimalLog(base); - } else { - baseLog = generalLog(base); - } - - uint256 baseLogTimesExp = (baseLog * _expN) / _expD; - if (baseLogTimesExp < OPT_EXP_MAX_VAL) { - return (optimalExp(baseLogTimesExp), MAX_PRECISION); - } else { - uint8 precision = findPositionInMaxExpArray(baseLogTimesExp); - return ( - generalExp( - baseLogTimesExp >> (MAX_PRECISION - precision), - precision - ), - precision - ); - } - } - - /** - Compute log(x / FIXED_1) * FIXED_1. - This functions assumes that "x >= FIXED_1", because the output would be negative otherwise. - */ - function generalLog(uint256 _x) internal pure returns (uint256) { - uint256 res = 0; - uint256 x = _x; - - // If x >= 2, then we compute the integer part of log2(x), which is larger than 0. - if (x >= FIXED_2) { - uint8 count = floorLog2(x / FIXED_1); - x >>= count; // now x < 2 - res = count * FIXED_1; - } - - // If x > 1, then we compute the fraction part of log2(x), which is larger than 0. - if (x > FIXED_1) { - for (uint8 i = MAX_PRECISION; i > 0; --i) { - x = (x * x) / FIXED_1; // now 1 < x < 4 - if (x >= FIXED_2) { - x >>= 1; // now 1 < x < 2 - res += ONE << (i - 1); - } - } - } - - return (res * LN2_NUMERATOR) / LN2_DENOMINATOR; - } - - /** - Compute the largest integer smaller than or equal to the binary logarithm of the input. - */ - function floorLog2(uint256 _n) internal pure returns (uint8) { - uint8 res = 0; - uint256 n = _n; - - if (n < 256) { - // At most 8 iterations - while (n > 1) { - n >>= 1; - res += 1; - } - } else { - // Exactly 8 iterations - for (uint8 s = 128; s > 0; s >>= 1) { - if (n >= (ONE << s)) { - n >>= s; - res |= s; - } - } - } - - return res; - } - - /** - The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent: - - This function finds the position of [the smallest value in "maxExpArray" larger than or equal to "x"] - - This function finds the highest position of [a value in "maxExpArray" larger than or equal to "x"] - */ - function findPositionInMaxExpArray(uint256 _x) - internal - view - returns (uint8) - { - uint8 lo = MIN_PRECISION; - uint8 hi = MAX_PRECISION; - - while (lo + 1 < hi) { - uint8 mid = (lo + hi) / 2; - if (maxExpArray[mid] >= _x) lo = mid; - else hi = mid; - } - - if (maxExpArray[hi] >= _x) return hi; - if (maxExpArray[lo] >= _x) return lo; - - assert(false); - return 0; - } - - /* solium-disable */ - /** - This function can be auto-generated by the script 'PrintFunctionGeneralExp.py'. - It approximates "e ^ x" via maclaurin summation: "(x^0)/0! + (x^1)/1! + ... + (x^n)/n!". - It returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy. - The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1". - The maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)". - */ - function generalExp(uint256 _x, uint8 _precision) - internal - pure - returns (uint256) - { - uint256 xi = _x; - uint256 res = 0; - - xi = (xi * _x) >> _precision; - res += xi * 0x3442c4e6074a82f1797f72ac0000000; // add x^02 * (33! / 02!) - xi = (xi * _x) >> _precision; - res += xi * 0x116b96f757c380fb287fd0e40000000; // add x^03 * (33! / 03!) - xi = (xi * _x) >> _precision; - res += xi * 0x045ae5bdd5f0e03eca1ff4390000000; // add x^04 * (33! / 04!) - xi = (xi * _x) >> _precision; - res += xi * 0x00defabf91302cd95b9ffda50000000; // add x^05 * (33! / 05!) - xi = (xi * _x) >> _precision; - res += xi * 0x002529ca9832b22439efff9b8000000; // add x^06 * (33! / 06!) - xi = (xi * _x) >> _precision; - res += xi * 0x00054f1cf12bd04e516b6da88000000; // add x^07 * (33! / 07!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000a9e39e257a09ca2d6db51000000; // add x^08 * (33! / 08!) - xi = (xi * _x) >> _precision; - res += xi * 0x000012e066e7b839fa050c309000000; // add x^09 * (33! / 09!) - xi = (xi * _x) >> _precision; - res += xi * 0x000001e33d7d926c329a1ad1a800000; // add x^10 * (33! / 10!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000002bee513bdb4a6b19b5f800000; // add x^11 * (33! / 11!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000003a9316fa79b88eccf2a00000; // add x^12 * (33! / 12!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000048177ebe1fa812375200000; // add x^13 * (33! / 13!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000005263fe90242dcbacf00000; // add x^14 * (33! / 14!) - xi = (xi * _x) >> _precision; - res += xi * 0x000000000057e22099c030d94100000; // add x^15 * (33! / 15!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000000057e22099c030d9410000; // add x^16 * (33! / 16!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000000000052b6b54569976310000; // add x^17 * (33! / 17!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000000000004985f67696bf748000; // add x^18 * (33! / 18!) - xi = (xi * _x) >> _precision; - res += xi * 0x000000000000003dea12ea99e498000; // add x^19 * (33! / 19!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000000000000031880f2214b6e000; // add x^20 * (33! / 20!) - xi = (xi * _x) >> _precision; - res += xi * 0x000000000000000025bcff56eb36000; // add x^21 * (33! / 21!) - xi = (xi * _x) >> _precision; - res += xi * 0x000000000000000001b722e10ab1000; // add x^22 * (33! / 22!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000000000000001317c70077000; // add x^23 * (33! / 23!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000000000000000000cba84aafa00; // add x^24 * (33! / 24!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000000000000000000082573a0a00; // add x^25 * (33! / 25!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000000000000000000005035ad900; // add x^26 * (33! / 26!) - xi = (xi * _x) >> _precision; - res += xi * 0x000000000000000000000002f881b00; // add x^27 * (33! / 27!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000000000000000000001b29340; // add x^28 * (33! / 28!) - xi = (xi * _x) >> _precision; - res += xi * 0x00000000000000000000000000efc40; // add x^29 * (33! / 29!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000000000000000000000007fe0; // add x^30 * (33! / 30!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000000000000000000000000420; // add x^31 * (33! / 31!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000000000000000000000000021; // add x^32 * (33! / 32!) - xi = (xi * _x) >> _precision; - res += xi * 0x0000000000000000000000000000001; // add x^33 * (33! / 33!) - - return - res / 0x688589cc0e9505e2f2fee5580000000 + _x + (ONE << _precision); // divide by 33! and then add x^1 / 1! + x^0 / 0! - } - - /** - Return log(x / FIXED_1) * FIXED_1 - Input range: FIXED_1 <= x <= LOG_EXP_MAX_VAL - 1 - Auto-generated via 'PrintFunctionOptimalLog.py' - */ - function optimalLog(uint256 x) internal pure returns (uint256) { - uint256 res = 0; - - uint256 y; - uint256 z; - uint256 w; - - if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd8) { - res += 0x40000000000000000000000000000000; - x = (x * FIXED_1) / 0xd3094c70f034de4b96ff7d5b6f99fcd8; - } - if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a7) { - res += 0x20000000000000000000000000000000; - x = (x * FIXED_1) / 0xa45af1e1f40c333b3de1db4dd55f29a7; - } - if (x >= 0x910b022db7ae67ce76b441c27035c6a1) { - res += 0x10000000000000000000000000000000; - x = (x * FIXED_1) / 0x910b022db7ae67ce76b441c27035c6a1; - } - if (x >= 0x88415abbe9a76bead8d00cf112e4d4a8) { - res += 0x08000000000000000000000000000000; - x = (x * FIXED_1) / 0x88415abbe9a76bead8d00cf112e4d4a8; - } - if (x >= 0x84102b00893f64c705e841d5d4064bd3) { - res += 0x04000000000000000000000000000000; - x = (x * FIXED_1) / 0x84102b00893f64c705e841d5d4064bd3; - } - if (x >= 0x8204055aaef1c8bd5c3259f4822735a2) { - res += 0x02000000000000000000000000000000; - x = (x * FIXED_1) / 0x8204055aaef1c8bd5c3259f4822735a2; - } - if (x >= 0x810100ab00222d861931c15e39b44e99) { - res += 0x01000000000000000000000000000000; - x = (x * FIXED_1) / 0x810100ab00222d861931c15e39b44e99; - } - if (x >= 0x808040155aabbbe9451521693554f733) { - res += 0x00800000000000000000000000000000; - x = (x * FIXED_1) / 0x808040155aabbbe9451521693554f733; - } - - z = y = x - FIXED_1; - w = (y * y) / FIXED_1; - res += - (z * (0x100000000000000000000000000000000 - y)) / - 0x100000000000000000000000000000000; - z = (z * w) / FIXED_1; - res += - (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / - 0x200000000000000000000000000000000; - z = (z * w) / FIXED_1; - res += - (z * (0x099999999999999999999999999999999 - y)) / - 0x300000000000000000000000000000000; - z = (z * w) / FIXED_1; - res += - (z * (0x092492492492492492492492492492492 - y)) / - 0x400000000000000000000000000000000; - z = (z * w) / FIXED_1; - res += - (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / - 0x500000000000000000000000000000000; - z = (z * w) / FIXED_1; - res += - (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / - 0x600000000000000000000000000000000; - z = (z * w) / FIXED_1; - res += - (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / - 0x700000000000000000000000000000000; - z = (z * w) / FIXED_1; - res += - (z * (0x088888888888888888888888888888888 - y)) / - 0x800000000000000000000000000000000; - - return res; - } - - /** - Return e ^ (x / FIXED_1) * FIXED_1 - Input range: 0 <= x <= OPT_EXP_MAX_VAL - 1 - Auto-generated via 'PrintFunctionOptimalExp.py' - */ - function optimalExp(uint256 x) internal pure returns (uint256) { - uint256 res = 0; - - uint256 y; - uint256 z; - - z = y = x % 0x10000000000000000000000000000000; - z = (z * y) / FIXED_1; - res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!) - z = (z * y) / FIXED_1; - res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!) - z = (z * y) / FIXED_1; - res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!) - z = (z * y) / FIXED_1; - res += z * 0x004807432bc18000; // add y^05 * (20! / 05!) - z = (z * y) / FIXED_1; - res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!) - z = (z * y) / FIXED_1; - res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!) - z = (z * y) / FIXED_1; - res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!) - z = (z * y) / FIXED_1; - res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!) - z = (z * y) / FIXED_1; - res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!) - z = (z * y) / FIXED_1; - res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!) - z = (z * y) / FIXED_1; - res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!) - z = (z * y) / FIXED_1; - res += z * 0x0000000017499f00; // add y^13 * (20! / 13!) - z = (z * y) / FIXED_1; - res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!) - z = (z * y) / FIXED_1; - res += z * 0x00000000001c6380; // add y^15 * (20! / 15!) - z = (z * y) / FIXED_1; - res += z * 0x000000000001c638; // add y^16 * (20! / 16!) - z = (z * y) / FIXED_1; - res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!) - z = (z * y) / FIXED_1; - res += z * 0x000000000000017c; // add y^18 * (20! / 18!) - z = (z * y) / FIXED_1; - res += z * 0x0000000000000014; // add y^19 * (20! / 19!) - z = (z * y) / FIXED_1; - res += z * 0x0000000000000001; // add y^20 * (20! / 20!) - res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0! - - if ((x & 0x010000000000000000000000000000000) != 0) - res = - (res * 0x1c3d6a24ed82218787d624d3e5eba95f9) / - 0x18ebef9eac820ae8682b9793ac6d1e776; - if ((x & 0x020000000000000000000000000000000) != 0) - res = - (res * 0x18ebef9eac820ae8682b9793ac6d1e778) / - 0x1368b2fc6f9609fe7aceb46aa619baed4; - if ((x & 0x040000000000000000000000000000000) != 0) - res = - (res * 0x1368b2fc6f9609fe7aceb46aa619baed5) / - 0x0bc5ab1b16779be3575bd8f0520a9f21f; - if ((x & 0x080000000000000000000000000000000) != 0) - res = - (res * 0x0bc5ab1b16779be3575bd8f0520a9f21e) / - 0x0454aaa8efe072e7f6ddbab84b40a55c9; - if ((x & 0x100000000000000000000000000000000) != 0) - res = - (res * 0x0454aaa8efe072e7f6ddbab84b40a55c5) / - 0x00960aadc109e7a3bf4578099615711ea; - if ((x & 0x200000000000000000000000000000000) != 0) - res = - (res * 0x00960aadc109e7a3bf4578099615711d7) / - 0x0002bf84208204f5977f9a8cf01fdce3d; - if ((x & 0x400000000000000000000000000000000) != 0) - res = - (res * 0x0002bf84208204f5977f9a8cf01fdc307) / - 0x0000003c6ab775dd0b95b4cbee7e65d11; - - return res; - } - /* solium-enable */ -} diff --git a/contracts/vaults/SingleAssetVault.sol b/contracts/vaults/SingleAssetVault.sol index 44ae46d5..91ee6b22 100644 --- a/contracts/vaults/SingleAssetVault.sol +++ b/contracts/vaults/SingleAssetVault.sol @@ -7,7 +7,6 @@ import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import "../interfaces/IVaultRegistry.sol"; import "../interfaces/IVault.sol"; import "../interfaces/IERC20.sol"; -import "hardhat/console.sol"; /// @title Vault /// @author Carl Farterson (@carlfarterson) diff --git a/deployment/rinkeby.json b/deployment/rinkeby.json deleted file mode 100644 index 6ad00873..00000000 --- a/deployment/rinkeby.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "network": "rinkeby", - "Hub Contract Address": "0x1159e16Cb27b3fD3254eb89De947293C77316EF9", - "VaultRegistry Contract Address": "0x19E8Fe397FF03A46Db25D1835013eD1b15da6638", - "SingleAssetVault Contract Address": "0xd2f726Ab2d2d53c7C51cddbb1D2621D3C34219A4", - "SingleAsset Factory Contract Address": "0xe2AF3717F1743D70a8924c2C3b731db33540F1D4", - "Block Number": "9430247" -} diff --git a/deployment/script-rinkeby.json b/deployment/script-rinkeby.json new file mode 100644 index 00000000..0e6b5c52 --- /dev/null +++ b/deployment/script-rinkeby.json @@ -0,0 +1,14 @@ +{ + "network": "rinkeby", + "Hub Contract Address": "0x10666bb554F63B900ED3aFC3bf83e9D0770d108e", + "VaultRegistry Contract Address": "0x9D2B2Ebd092a69A00c724b9889C216BB3571A651", + "SingleAssetVault Contract Address": "0x3Ea10CD4f2EF8c6b555531859cFF153bE197dbEe", + "SingleAsset Factory Contract Address": "0x6997e4C8A20ECf92B915Cb3886ff4726D811015D", + "Curve Registry Contract Address": "0x134fcE5B060895c845aA7eE3b6e2CCE624a03F5f", + "Bancor Curve Contract Address": "0x3E9A475284D0290faa2307eF49009544CAc17C3a", + "Foundry Contract Address": "0x7FC3C7805095a6863243bFc73Da563A1E1CA2763", + "MeToken Factory Contract Address": "0x27741a9e9d2265bC956e7533BB6Fe59dcfeE1538", + "MeToken Registry Contract Address": "0xd4ca9c1C0C1f13779bfe787EfE098fcFA1E7D075", + "WeightedAverage Contract Address": "0x889c93468Ee077d3cD89F318C01a0bc9D707992B", + "Block Number": "9464019" +} diff --git a/scripts/deploy.ts b/scripts/deploy.ts index d7d63a4f..5830b47e 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -1,4 +1,4 @@ -import { network, run, ethers, getNamedAccounts } from "hardhat"; +import { network, run, ethers } from "hardhat"; import { Hub } from "../artifacts/types/Hub"; import { VaultRegistry } from "../artifacts/types/VaultRegistry"; import { SingleAssetVault } from "../artifacts/types/SingleAssetVault"; @@ -11,11 +11,15 @@ import { BancorZeroCurve } from "../artifacts/types/BancorZeroCurve"; import { CurveRegistry } from "../artifacts/types/CurveRegistry"; import { Foundry } from "../artifacts/types/Foundry"; import { WeightedAverage } from "../artifacts/types/WeightedAverage"; +import { BigNumber } from "ethers"; const ETHERSCAN_CHAIN_IDS = [1, 3, 4, 5, 42]; const SUPPORTED_NETWORK = [1, 4, 100, 31337]; const contracts: any[] = []; const REFUND_RATIO = 50000; +const PRECISION = BigNumber.from(10).pow(18); +const MAX_WEIGHT = 1000000; const deployDir = "deployment"; + function currencySymbol(chainId: number) { switch (chainId.toString()) { case "100": @@ -24,6 +28,21 @@ function currencySymbol(chainId: number) { return "ETH"; } } +function currencyAddress(chainId: number) { + switch (chainId.toString()) { + // Rinkeby + case "4": + return "0x92d75D18C4A2aDF86365EcFd5219f13AfED5103C"; + + // Hardhat + case "31337": + return "0x6B175474E89094C44Da98b954EedeAC495271d0F"; + + default: { + throw new Error("Un-supported network"); + } + } +} function printLog(msg: string) { if (process.stdout.isTTY) { process.stdout.clearLine(-1); @@ -91,40 +110,39 @@ async function main() { hub.address, meTokenFactory.address ); - contracts.push(meTokenRegistry.address); printLog("Registering Bancor Curve to curve registry..."); - await curveRegistry.register(bancorZeroCurve.address); - + let tx = await curveRegistry.register(bancorZeroCurve.address); + await tx.wait(); printLog("Initializing SingleAssetVault..."); - const { DAI } = await getNamedAccounts(); - await singleAssetVault.initialize( + tx = await singleAssetVault.initialize( foundry.address, - DAI, + currencyAddress(chainId), ethers.utils.toUtf8Bytes("") ); - + await tx.wait(); printLog("Initializing hub Contract..."); - await vaultRegistry.approve(singleAssetFactory.address); - - await hub.initialize( + tx = await vaultRegistry.approve(singleAssetFactory.address); + await tx.wait(); + tx = await hub.initialize( foundry.address, vaultRegistry.address, curveRegistry.address ); + await tx.wait(); + const baseY = PRECISION.div(1000).toString(); + const reserveWeight = BigNumber.from(MAX_WEIGHT).div(2).toString(); const encodedValueSet = ethers.utils.defaultAbiCoder.encode( ["uint256", "uint32"], - [ethers.utils.parseEther("1000000000000000000"), 5000] + [baseY, reserveWeight] ); - - const tx = await hub.register( + tx = await hub.register( singleAssetFactory.address, bancorZeroCurve.address, - DAI, + currencyAddress(chainId), REFUND_RATIO, encodedValueSet, ethers.utils.toUtf8Bytes("") ); - await tx.wait(); const receipt = await deployer.provider.getTransactionReceipt(tx.hash); const isEtherscan = ETHERSCAN_CHAIN_IDS.includes(chainId); @@ -143,6 +161,10 @@ async function main() { singleAssetVault.address, ], }); + await run(TASK_VERIFY, { + address: meTokenRegistry.address, + constructorArgsParams: [hub.address, meTokenFactory.address], + }); } catch (error) { console.error(`Error verifying ${singleAssetFactory.address}: `, error); } diff --git a/test/contracts/curves/BancorZeroCurve.ts b/test/contracts/curves/BancorZeroCurve.ts index b08ac1d2..0c989aef 100644 --- a/test/contracts/curves/BancorZeroCurve.ts +++ b/test/contracts/curves/BancorZeroCurve.ts @@ -14,7 +14,6 @@ import { WeightedAverage } from "../../../artifacts/types/WeightedAverage"; import { VaultRegistry } from "../../../artifacts/types/VaultRegistry"; import { impersonate } from "../../utils/hardhatNode"; import { deploy, getContractAt } from "../../utils/helpers"; -import { exit } from "process"; import { expect } from "chai"; describe("BancorZeroCurve", () => { @@ -86,9 +85,7 @@ describe("BancorZeroCurve", () => { // Max weight = 1000000 if reserveWeight = 0.5 == Max weight / 2 // this gives us m = 1/1000 const baseY = PRECISION.div(1000).toString(); - console.log({ baseY }); const reserveWeight = BigNumber.from(MAX_WEIGHT).div(2).toString(); - console.log({ reserveWeight }); const encodedValueSet = ethers.utils.defaultAbiCoder.encode( ["uint256", "uint32"], [baseY, reserveWeight] @@ -193,7 +190,7 @@ describe("BancorZeroCurve", () => { one.mul(999999999999999) ); - expect(estimate).to.equal(ethers.utils.parseEther("0.001999999999999999")); + expect(estimate).to.equal(ethers.utils.parseEther("0.002")); }); it("registerTarget() should work", async () => { const baseY = PRECISION.div(1000); @@ -229,8 +226,6 @@ describe("BancorZeroCurve", () => { it("calculateTargetMintReturn() should work", async () => { const detail = await bancorZeroCurve.getDetails(hubId); const targetReserveWeight = detail.targetReserveWeight; - console.log(` - targetReserveWeight:${targetReserveWeight.toString()}`); let amount = one.mul(2); // 2/(2000^((1/0.98)−1))* 1944.930817973436691629^((1/0.98)−1)) == 1,998860701224224 @@ -284,70 +279,4 @@ describe("BancorZeroCurve", () => { it("finishUpdate should work", async () => { // TODO }); - /* it("register()", async () => { - // const index = 1; - // const key = "0xbccc714d56bc0da0fd33d96d2a87b680dd6d0df6"; - - const encodedValueSet = ethers.utils.defaultAbiCoder.encode( - ["uint256"], - [131] - ); - //const key = encodedValueSet; - const key = "0x0000000000000000000000000000000000000083"; - // const key = "0x0000000000000000000000000000000000000000"; - // const key = ethers.utils.hexlify(0); - console.log(` Key:${key} `); - - - for (let index = 0; index < 10; index++) { - const aaa = await ethers.provider.getStorageAt( - bancorZeroCurve.address, - index - ); - console.log(` AAAAAAA:${aaa} --index:${index}`); - - // The pre-image used to compute the Storage location - const newKeyPreimage = ethers.utils.concat([ - // Mappings' keys in Solidity must all be word-aligned (32 bytes) - ethers.utils.hexZeroPad(key, 32), - - // Similarly with the slot-index into the Solidity variable layout - ethers.utils.hexZeroPad(BigNumber.from(index).toHexString(), 32), - ]); - - console.log("New Key Preimage:", ethers.utils.hexlify(newKeyPreimage)); - - const newKey = ethers.utils.keccak256(newKeyPreimage); - console.log("New Key:", newKey); - // "0xafef6be2b419f4d69d56fe34788202bf06650015554457a2470181981bcce7ef" - - const totalOutstandingDebt = await ethers.provider.getStorageAt( - bancorZeroCurve.address, - newKey - ); - if (totalOutstandingDebt != ethers.constants.HashZero) { - console.log(` - - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ************************* - ********************************************************************** - RES:${totalOutstandingDebt} - `); - } - } - // TODO - }); */ }); diff --git a/test/contracts/registries/MeTokenRegistry.ts b/test/contracts/registries/MeTokenRegistry.ts index 973cdc5c..4c56c8e9 100644 --- a/test/contracts/registries/MeTokenRegistry.ts +++ b/test/contracts/registries/MeTokenRegistry.ts @@ -123,6 +123,13 @@ describe("MeTokenRegistry.sol", () => { expect(await meToken.decimals()).to.equal(18); expect(await meToken.totalSupply()).to.equal(0); }); + it("User can't create two meToken", async () => { + const name = "Carl0 meToken"; + const symbol = "CARL"; + await expect( + meTokenRegistry.connect(account0).register(name, "CARL", hubId, 0) + ).to.be.revertedWith("msg.sender already owns a meToke"); + }); it("User can create a meToken with 100 DAI as collateral", async () => { const amount = 100; diff --git a/test/contracts/utils/power.ts b/test/contracts/utils/power.ts deleted file mode 100644 index 99a2d546..00000000 --- a/test/contracts/utils/power.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { BigNumber } from "ethers"; -import assert from "assert"; -import { expect } from "chai"; -import { ethers } from "hardhat"; -import { PowerMock } from "../../../artifacts/types/PowerMock"; -import { deploy, maxExpArray, maxValArray } from "../../utils/helpers"; - -describe("Power", () => { - let formula: PowerMock; - const MIN_PRECISION = 32; - const MAX_PRECISION = 127; - before(async () => { - formula = await deploy("PowerMock"); - }); - - for (let precision = MIN_PRECISION; precision <= MAX_PRECISION; precision++) { - let maxExp = BigNumber.from(maxExpArray[precision]); - let shlVal = BigNumber.from(2).pow(MAX_PRECISION - precision); - - let tuples = [ - { - input: maxExp.add(0).mul(shlVal).sub(1), - output: BigNumber.from(precision - 0), - }, - { - input: maxExp.add(0).mul(shlVal).sub(0), - output: BigNumber.from(precision - 0), - }, - { - input: maxExp.add(1).mul(shlVal).sub(1), - output: BigNumber.from(precision - 0), - }, - { - input: maxExp.add(1).mul(shlVal).sub(0), - output: BigNumber.from(precision - 1), - }, - ]; - - for (let index = 0; index < tuples.length; index++) { - let input = tuples[index].input; - let output = tuples[index].output; - let test = `Function findPositionInMaxExpArray(0x${input.toHexString()})`; - - it(`${test}:`, async () => { - try { - let retVal = await formula.findPositionInMaxExpArrayTest(input); - expect(retVal).to.equal(output); - expect( - precision > MIN_PRECISION || !output.lt(BigNumber.from(precision)) - ).to.be.true; - } catch (error) { - expect( - precision === MIN_PRECISION && output.lt(BigNumber.from(precision)) - ).to.be.true; - } - }); - } - } - for (let precision = MIN_PRECISION; precision <= MAX_PRECISION; precision++) { - let minExp = BigNumber.from(maxExpArray[precision - 1]).add(1); - let minVal = BigNumber.from(2).pow(precision); - let test = `Function fixedExp(0x${minExp.toHexString()}, ${precision})`; - - it(`${test}:`, async () => { - let retVal = await formula.generalExpTest(minExp, precision); - expect(retVal.gte(minVal)).to.be.true; - }); - } - for (let n = 1; n <= 255; n++) { - let tuples = [ - { input: BigNumber.from(2).pow(n), output: BigNumber.from(n) }, - { - input: BigNumber.from(2).pow(n).add(1), - output: BigNumber.from(n), - }, - { - input: BigNumber.from(2) - .pow(n + 1) - .sub(1), - output: BigNumber.from(n), - }, - ]; - - for (let index = 0; index < tuples.length; index++) { - let input = tuples[index].input; - let output = tuples[index].output; - let test = `Function floorLog2(0x${input.toHexString()})`; - - it(`${test}:`, async () => { - let retVal = await formula.floorLog2Test(input); - expect(retVal).to.equal(output); - }); - } - } -});