From b6f1c80c8dfb13c09d93fc2e624875f68759cd09 Mon Sep 17 00:00:00 2001 From: danielalcarraz Date: Sun, 16 Feb 2025 19:22:27 -0500 Subject: [PATCH 1/2] fix refType3 bugs --- .../strategies/vault/lending/VaultBorrowStrategy.sol | 3 +-- .../vault/rebalance/VaultExternalRebalanceStrategy.sol | 2 +- contracts/viewers/vault/VaultPoolViewer.sol | 3 ++- package.json | 4 ++-- yarn.lock | 8 ++++---- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/contracts/strategies/vault/lending/VaultBorrowStrategy.sol b/contracts/strategies/vault/lending/VaultBorrowStrategy.sol index 8cc17a3..f616a35 100644 --- a/contracts/strategies/vault/lending/VaultBorrowStrategy.sol +++ b/contracts/strategies/vault/lending/VaultBorrowStrategy.sol @@ -86,9 +86,8 @@ contract VaultBorrowStrategy is VaultBaseRebalanceStrategy, BorrowStrategy { if(isRefType3) { uint256 reservedLPTokens = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)); - if(lpTokens >= reservedLPTokens) revert ExcessiveBorrowing(); unchecked { - reservedLPTokens = reservedLPTokens - lpTokens; + reservedLPTokens = reservedLPTokens - GSMath.min(reservedLPTokens, lpTokens); } s.setUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS), reservedLPTokens); } diff --git a/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol b/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol index 29edd79..91002cd 100644 --- a/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol +++ b/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol @@ -46,7 +46,7 @@ contract VaultExternalRebalanceStrategy is VaultBaseLongStrategy, ExternalRebala // Get loan for tokenId, revert if not loan creator LibStorage.Loan storage _loan = _getLoan(tokenId); - if(_loan.refType == 3) revert InvalidRefType(); + if(_loan.refType != 3) revert InvalidRefType(); updateLoan(_loan); diff --git a/contracts/viewers/vault/VaultPoolViewer.sol b/contracts/viewers/vault/VaultPoolViewer.sol index 47eb29e..0fb95fc 100644 --- a/contracts/viewers/vault/VaultPoolViewer.sol +++ b/contracts/viewers/vault/VaultPoolViewer.sol @@ -70,6 +70,7 @@ contract VaultPoolViewer is PoolViewer, IVaultPoolViewer { if(_loanData.liquidity == 0) { return false; } + _loanData.accFeeIndex = _getLoanLastFeeIndex(_loanData); address refAddr = address(0); if(_loanData.refType == 3) { refAddr = _loanData.refAddr; @@ -165,7 +166,7 @@ contract VaultPoolViewer is PoolViewer, IVaultPoolViewer { (,data.LP_TOKEN_BORROWED_PLUS_INTEREST, borrowedInvariant) = IShortStrategy(data.shortStrategy) .getLatestBalances(data.lastFeeIndex, borrowedInvariant, data.LP_TOKEN_BALANCE, lastCFMMInvariant, lastCFMMTotalSupply); - data.LP_TOKEN_BORROWED_PLUS_INTEREST += lastCFMMFeeIndex * lastCFMMTotalSupply / lastCFMMInvariant; + data.LP_TOKEN_BORROWED_PLUS_INTEREST += (lastCFMMFeeIndex * lastCFMMTotalSupply + (lastCFMMInvariant - 1))/ lastCFMMInvariant; data.BORROWED_INVARIANT = uint128(borrowedInvariant + lastCFMMFeeIndex); data.LP_INVARIANT = uint128(data.LP_TOKEN_BALANCE * lastCFMMInvariant / lastCFMMTotalSupply); diff --git a/package.json b/package.json index 8a9ff61..cc3d100 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gammaswap/v1-implementations", - "version": "1.2.13", + "version": "1.2.14", "description": "Pool and strategies implementation contracts for GammaSwap V1 protocol", "homepage": "https://gammaswap.com", "scripts": { @@ -71,7 +71,7 @@ "typescript": "^4.7.4" }, "dependencies": { - "@gammaswap/v1-core": "^1.2.13", + "@gammaswap/v1-core": "^1.2.14", "@openzeppelin/contracts": "^4.7.0" } } diff --git a/yarn.lock b/yarn.lock index b14f881..2f293e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -449,10 +449,10 @@ "@ethersproject/properties" "^5.7.0" "@ethersproject/strings" "^5.7.0" -"@gammaswap/v1-core@^1.2.13": - version "1.2.13" - resolved "https://npm.pkg.github.com/download/@gammaswap/v1-core/1.2.13/26f6719af9d6665640ade967b896fc2e3c0ec232#26f6719af9d6665640ade967b896fc2e3c0ec232" - integrity sha512-MqbWW584MMVmm6+iMToyxn7wp5F1dpwFohMp531qokrRHJ8qyC0Kj6l2v2klxsWvFHVe9qi9Vm3HeUFg7YuwoA== +"@gammaswap/v1-core@^1.2.14": + version "1.2.14" + resolved "https://npm.pkg.github.com/download/@gammaswap/v1-core/1.2.14/a282b6841d31b06e9625f5dc3b979668febf1b5b#a282b6841d31b06e9625f5dc3b979668febf1b5b" + integrity sha512-CwsxyLQZmSPKiXWNllyaVXC+xIoX7agcWOF99l6V0gJCKfsNZfzNmiZzGzLQG46sOxa2Se1NPey4o/lOH/TNQg== dependencies: "@openzeppelin/contracts" "^4.7.0" From 4acbc3fd5685f19fe94cb2e35f31f7c3a745679e Mon Sep 17 00:00:00 2001 From: danielalcarraz Date: Sun, 16 Feb 2025 19:50:56 -0500 Subject: [PATCH 2/2] updating unit tests for new foundry version --- test/foundry/FullMath.t.sol | 84 ++++++++++++++++++++++++++----------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/test/foundry/FullMath.t.sol b/test/foundry/FullMath.t.sol index c160f71..8dec771 100644 --- a/test/foundry/FullMath.t.sol +++ b/test/foundry/FullMath.t.sol @@ -7,6 +7,11 @@ import "@gammaswap/v1-core/contracts/libraries/GSMath.sol"; import "../../contracts/libraries/FullMath.sol"; contract FullMathTest is Test { + MathFunctions math; + + function setUp() public { + math = new MathFunctions(); + } // Babylonian Method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint256 y) internal pure returns (uint256 z) { @@ -132,32 +137,32 @@ contract FullMathTest is Test { assertEq(a1, type(uint256).max); vm.expectRevert("ADDITION_OVERFLOW"); - (a0, a1) = FullMath.add512x512(1, 0, type(uint256).max, type(uint256).max); + (a0, a1) = math.add512x512(1, 0, type(uint256).max, type(uint256).max); } function testAdd512Revert() public { vm.expectRevert("ADDITION_OVERFLOW"); - FullMath.add512x512(type(uint256).max, type(uint256).max, 1, 0); + math.add512x512(type(uint256).max, type(uint256).max, 1, 0); } function testAdd512Revert2() public { vm.expectRevert("ADDITION_OVERFLOW"); - FullMath.add512x512(0, type(uint256).max, 0, 1); + math.add512x512(0, type(uint256).max, 0, 1); } function testAdd512Revert3() public { vm.expectRevert("ADDITION_OVERFLOW"); - FullMath.add512x512(0, 1, 0, type(uint256).max); + math.add512x512(0, 1, 0, type(uint256).max); } function testAdd512Revert4() public { vm.expectRevert("ADDITION_OVERFLOW"); - FullMath.add512x512(0, type(uint256).max, 0, type(uint256).max); + math.add512x512(0, type(uint256).max, 0, type(uint256).max); } function testAdd512Revert5() public { vm.expectRevert("ADDITION_OVERFLOW"); - (uint256 r0, uint256 r1) = FullMath.add512x512(type(uint256).max-2, type(uint256).max, 3, 0); + (uint256 r0, uint256 r1) = math.add512x512(type(uint256).max-2, type(uint256).max, 3, 0); } function testAddSubtract(uint256 num1, uint256 num2) public { @@ -196,7 +201,7 @@ contract FullMathTest is Test { if(hasHighBit) { vm.expectRevert("ADDITION_OVERFLOW"); - FullMath.add512x512(0, num1, 0, num2); + math.add512x512(0, num1, 0, num2); } } @@ -242,22 +247,22 @@ contract FullMathTest is Test { assertEq(a1, 0); vm.expectRevert("SUBTRACTION_UNDERFLOW"); - FullMath.sub512x512(0, 1, 1, 1); + math.sub512x512(0, 1, 1, 1); } function testSub512Revert() public { vm.expectRevert("SUBTRACTION_UNDERFLOW"); - FullMath.sub512x512(0, 0, 1, 0); + math.sub512x512(0, 0, 1, 0); } function testSub512Revert2() public { vm.expectRevert("SUBTRACTION_UNDERFLOW"); - FullMath.sub512x512(0, 0, 1, 0); + math.sub512x512(0, 0, 1, 0); } function testSub512Revert3() public { vm.expectRevert("SUBTRACTION_UNDERFLOW"); - FullMath.sub512x512(0, type(uint256).max, 1, type(uint256).max); + math.sub512x512(0, type(uint256).max, 1, type(uint256).max); } function testSub512(uint256 a0, uint256 a1, uint256 b0, uint256 b1) public { @@ -267,12 +272,12 @@ contract FullMathTest is Test { (c0, c1) = FullMath.sub512x512(a0, a1, b0, b1); assertEq(FullMath.gt512(c0, c1, 0, 0), true); vm.expectRevert("SUBTRACTION_UNDERFLOW"); - FullMath.sub512x512(b0, b1, a0, a1); + math.sub512x512(b0, b1, a0, a1); } else if(FullMath.lt512(a0, a1, b0, b1)) { (c0, c1) = FullMath.sub512x512(b0, b1, a0, a1); assertEq(FullMath.gt512(c0, c1, 0, 0), true); vm.expectRevert("SUBTRACTION_UNDERFLOW"); - FullMath.sub512x512(a0, a1, b0, b1); + math.sub512x512(a0, a1, b0, b1); } else { (c0, c1) = FullMath.sub512x512(a0, a1, b0, b1); assertEq(FullMath.eq512(c0, c1, 0, 0), true); @@ -622,7 +627,7 @@ contract FullMathTest is Test { if(u1 > 0) { vm.expectRevert("MULTIPLICATION_OVERFLOW"); - (uint256 x0, uint256 x1) = FullMath.mul512x256(0, num1, num2); + (uint256 x0, uint256 x1) = math.mul512x256(0, num1, num2); } else { if(num2 > 0) { (uint256 x0, uint256 x1) = FullMath.div512x256(v0, v1, num2); @@ -646,7 +651,7 @@ contract FullMathTest is Test { (uint256 y0, uint256 y1) = FullMath.add512x512(u0, 0, x1, 0); if(y1 > 0) { vm.expectRevert("MULTIPLICATION_OVERFLOW"); - FullMath.mul512x256(num1, num2, num3); + math.mul512x256(num1, num2, num3); } } } @@ -656,7 +661,7 @@ contract FullMathTest is Test { uint256 num2 = type(uint256).max; uint256 num3 = 2; vm.expectRevert("MULTIPLICATION_OVERFLOW"); - FullMath.mul512x256(num1, num2, num3); + math.mul512x256(num1, num2, num3); } function testMul512x256Revert2() public { @@ -671,7 +676,7 @@ contract FullMathTest is Test { num1++; vm.expectRevert("MULTIPLICATION_OVERFLOW"); - FullMath.mul512x256(num1, num2, num3); + math.mul512x256(num1, num2, num3); } function testMul512x256Revert3() public { @@ -686,7 +691,7 @@ contract FullMathTest is Test { ++num1; vm.expectRevert("MULTIPLICATION_OVERFLOW"); - FullMath.mul512x256(num1, num2, num3); + math.mul512x256(num1, num2, num3); } function testMul512x256Fixed() public { @@ -726,7 +731,7 @@ contract FullMathTest is Test { assertEq(v1, num2*num3); vm.expectRevert("MULTIPLICATION_OVERFLOW"); - FullMath.mul512x256(0, type(uint256).max, 2); + math.mul512x256(0, type(uint256).max, 2); } function testDivFixed512x256_128(uint128 num1, uint128 num2, uint128 num3) public { @@ -892,10 +897,10 @@ contract FullMathTest is Test { assertEq(u1, 0); vm.expectRevert("DIVISION_BY_ZERO"); - FullMath.div512x256(u0, u1, num3); + math.div512x256(u0, u1, num3); vm.expectRevert("DIVISION_BY_ZERO"); - FullMath.divRem512x256(u0, u1, num3); + math.divRem512x256(u0, u1, num3); } function testDiv512x256(uint256 num1, uint256 num2, uint256 num3) public { @@ -930,7 +935,7 @@ contract FullMathTest is Test { function testMulDiv512(uint256 num1, uint256 num2, uint256 num3) public { if(num3 == 0) { vm.expectRevert("MULDIV_ZERO_DIVISOR"); - FullMath.mulDiv512(num1, num2, 0); + math.mulDiv512(num1, num2, 0); return; } @@ -950,7 +955,7 @@ contract FullMathTest is Test { function testMulDiv256(uint256 num1, uint256 num2, uint256 num3) public { if(num3 == 0) { vm.expectRevert("MULDIV_ZERO_DIVISOR"); - FullMath.mulDiv512(num1, num2, num3); + math.mulDiv512(num1, num2, num3); return; } if(num1 == 0 || num2 ==0) { @@ -976,8 +981,39 @@ contract FullMathTest is Test { assertEq(v1, 0); } else { vm.expectRevert("MULDIV_OVERFLOW"); - FullMath.mulDiv256(num1, num2, num3); + math.mulDiv256(num1, num2, num3); } } } } + +contract MathFunctions { + + function add512x512(uint256 a0, uint256 a1, uint256 b0, uint256 b1) external pure returns (uint256, uint256) { + return FullMath.add512x512(a0, a1, b0, b1); + } + + function sub512x512(uint256 a0, uint256 a1, uint256 b0, uint256 b1) external pure returns (uint256, uint256) { + return FullMath.sub512x512(a0, a1, b0, b1); + } + + function mul512x256(uint256 a0, uint256 a1, uint256 b) external pure returns (uint256, uint256) { + return FullMath.mul512x256(a0, a1, b); + } + + function div512x256(uint256 a0, uint256 a1, uint256 b) external pure returns(uint256, uint256) { + return FullMath.div512x256(a0, a1, b); + } + + function divRem512x256(uint256 a0, uint256 a1, uint256 b) external pure returns(uint256) { + return FullMath.divRem512x256(a0, a1, b); + } + + function mulDiv256(uint256 a, uint256 b, uint256 c) external pure returns(uint256) { + return FullMath.mulDiv256(a, b, c); + } + + function mulDiv512(uint256 num1, uint256 num2, uint256 num3) external pure returns(uint256, uint256) { + return FullMath.mulDiv512(num1, num2, num3); + } +} \ No newline at end of file