From de960522be504ea062bd47b95387d04fecb0f47f Mon Sep 17 00:00:00 2001 From: danielalcarraz Date: Thu, 13 Mar 2025 15:59:04 -0400 Subject: [PATCH 1/3] make vault storage keys hashed keys --- contracts/pools/VaultGammaPool.sol | 15 +++-- .../vault/base/VaultBaseRepayStrategy.sol | 4 +- .../vault/base/VaultBaseStrategy.sol | 16 +++-- .../vault/lending/VaultBorrowStrategy.sol | 10 ++-- .../VaultExternalRebalanceStrategy.sol | 8 +-- contracts/test/TestVaultGammaPool.sol | 24 ++++++++ .../vault/TestVaultBaseStrategy.sol | 58 +++++++++++++++++++ test/foundry/VaultGammaPool.t.sol | 48 +++++++++++++++ 8 files changed, 161 insertions(+), 22 deletions(-) create mode 100644 contracts/test/TestVaultGammaPool.sol create mode 100644 contracts/test/strategies/vault/TestVaultBaseStrategy.sol create mode 100644 test/foundry/VaultGammaPool.t.sol diff --git a/contracts/pools/VaultGammaPool.sol b/contracts/pools/VaultGammaPool.sol index a41f3b4..002d4de 100644 --- a/contracts/pools/VaultGammaPool.sol +++ b/contracts/pools/VaultGammaPool.sol @@ -25,8 +25,7 @@ contract VaultGammaPool is CPMMGammaPool, IVaultGammaPool { /// @dev See {IVaultGammaPool-getReservedBalances} function getReservedBalances() external virtual override view returns(uint256, uint256) { - return(s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_BORROWED_INVARIANT)), - s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS))); + return(s.getUint256(RESERVED_BORROWED_INVARIANT()), s.getUint256(RESERVED_LP_TOKENS())); } /// @dev See {IGammaPoolExternal-liquidateExternally} @@ -43,7 +42,7 @@ contract VaultGammaPool is CPMMGammaPool, IVaultGammaPool { /// @dev See {GammaPoolERC4626-maxAssets} function maxAssets(uint256 assets) internal view virtual override returns(uint256) { uint256 lpTokenBalance = s.LP_TOKEN_BALANCE; // CFMM LP tokens in GammaPool that have not been borrowed - lpTokenBalance = lpTokenBalance - GSMath.min(s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)), lpTokenBalance); + lpTokenBalance = lpTokenBalance - GSMath.min(s.getUint256(RESERVED_LP_TOKENS()), lpTokenBalance); if(assets < lpTokenBalance){ // limit assets available to withdraw to what has not been borrowed return assets; } @@ -59,7 +58,7 @@ contract VaultGammaPool is CPMMGammaPool, IVaultGammaPool { pool: address(this), paramsStore: _factory, BORROWED_INVARIANT: s.BORROWED_INVARIANT, - RESERVED_BORROWED_INVARIANT: s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_BORROWED_INVARIANT)), + RESERVED_BORROWED_INVARIANT: s.getUint256(RESERVED_BORROWED_INVARIANT()), latestCfmmInvariant: _getLatestCFMMInvariant(), latestCfmmTotalSupply: _getLatestCFMMTotalSupply(), LAST_BLOCK_NUMBER: s.LAST_BLOCK_NUMBER, @@ -72,4 +71,12 @@ contract VaultGammaPool is CPMMGammaPool, IVaultGammaPool { }) ); } + + function RESERVED_LP_TOKENS() internal virtual pure returns(uint256) { + return uint256(0x1d4997f9934f878df7106acada1ff771325c95fb5c98472c2bbed4497048bf65); + } + + function RESERVED_BORROWED_INVARIANT() internal virtual pure returns(uint256) { + return uint256(0x54f559f312bc80877ff037529d330829149d3630a04e9d467f30196e91b6ad9d); + } } diff --git a/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol b/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol index 9ad93fb..ad9b813 100644 --- a/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol +++ b/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol @@ -77,12 +77,12 @@ abstract contract VaultBaseRepayStrategy is BaseRepayStrategy, VaultBaseRebalanc } if(_loan.refType == 3 && _paidLiquidity > 0) { - uint256 reservedBorrowedInvariant = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_BORROWED_INVARIANT)); + uint256 reservedBorrowedInvariant = s.getUint256(RESERVED_BORROWED_INVARIANT()); _paidLiquidity = GSMath.min(reservedBorrowedInvariant, _paidLiquidity); unchecked { reservedBorrowedInvariant = reservedBorrowedInvariant - _paidLiquidity; } - s.setUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_BORROWED_INVARIANT), reservedBorrowedInvariant); + s.setUint256(RESERVED_BORROWED_INVARIANT(), reservedBorrowedInvariant); } } } diff --git a/contracts/strategies/vault/base/VaultBaseStrategy.sol b/contracts/strategies/vault/base/VaultBaseStrategy.sol index 52e0956..8966f78 100644 --- a/contracts/strategies/vault/base/VaultBaseStrategy.sol +++ b/contracts/strategies/vault/base/VaultBaseStrategy.sol @@ -17,8 +17,7 @@ abstract contract VaultBaseStrategy is BaseStrategy { /// @param lastFeeIndex - interest accrued to loans in GammaPool /// @return newBorrowedInvariant - borrowed invariant with accrued interest function accrueBorrowedInvariant(uint256 borrowedInvariant, uint256 lastFeeIndex) internal virtual override view returns(uint256) { - uint256 reservedBorrowedInvariant = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_BORROWED_INVARIANT)); - reservedBorrowedInvariant = GSMath.min(borrowedInvariant,reservedBorrowedInvariant); + uint256 reservedBorrowedInvariant = GSMath.min(borrowedInvariant,s.getUint256(RESERVED_BORROWED_INVARIANT())); unchecked { borrowedInvariant = borrowedInvariant - reservedBorrowedInvariant; } @@ -39,9 +38,8 @@ abstract contract VaultBaseStrategy is BaseStrategy { function checkExpectedUtilizationRate(uint256 lpTokens, bool isLoan) internal virtual override view { uint256 lastCFMMInvariant = s.lastCFMMInvariant; uint256 lastCFMMTotalSupply = s.lastCFMMTotalSupply; - uint256 reservedLPTokens = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)); - uint256 reservedLPInvariant = convertLPToInvariant(reservedLPTokens, lastCFMMInvariant, lastCFMMTotalSupply); + uint256 reservedLPInvariant = convertLPToInvariant(s.getUint256(RESERVED_LP_TOKENS()), lastCFMMInvariant, lastCFMMTotalSupply); uint256 lpTokenInvariant = convertLPToInvariant(lpTokens, lastCFMMInvariant, lastCFMMTotalSupply); uint256 lpInvariant = s.LP_INVARIANT; lpInvariant = lpInvariant >= reservedLPInvariant ? lpInvariant - reservedLPInvariant : 0; @@ -57,11 +55,19 @@ abstract contract VaultBaseStrategy is BaseStrategy { } function getAdjLPTokenBalance() internal virtual view returns(uint256 lpTokenBalance) { - uint256 reservedLPTokens = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)); + uint256 reservedLPTokens = s.getUint256(RESERVED_LP_TOKENS()); lpTokenBalance = s.LP_TOKEN_BALANCE; reservedLPTokens = GSMath.min(lpTokenBalance, reservedLPTokens); unchecked { lpTokenBalance = lpTokenBalance - reservedLPTokens; } } + + function RESERVED_LP_TOKENS() internal virtual pure returns(uint256) { + return uint256(0x1d4997f9934f878df7106acada1ff771325c95fb5c98472c2bbed4497048bf65); + } + + function RESERVED_BORROWED_INVARIANT() internal virtual pure returns(uint256) { + return uint256(0x54f559f312bc80877ff037529d330829149d3630a04e9d467f30196e91b6ad9d); + } } diff --git a/contracts/strategies/vault/lending/VaultBorrowStrategy.sol b/contracts/strategies/vault/lending/VaultBorrowStrategy.sol index f616a35..972937a 100644 --- a/contracts/strategies/vault/lending/VaultBorrowStrategy.sol +++ b/contracts/strategies/vault/lending/VaultBorrowStrategy.sol @@ -48,8 +48,7 @@ contract VaultBorrowStrategy is VaultBaseRebalanceStrategy, BorrowStrategy { uint256 lpInvariant = s.LP_INVARIANT; uint256 reservedLPInvariant = 0; if(!isRefType3) { - reservedLPInvariant = convertLPToInvariant(s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)), - lastCFMMInvariant, lastCFMMTotalSupply); + reservedLPInvariant = convertLPToInvariant(s.getUint256(RESERVED_LP_TOKENS()), lastCFMMInvariant, lastCFMMTotalSupply); reservedLPInvariant = GSMath.min(lpInvariant, reservedLPInvariant); unchecked { lpInvariant = lpInvariant - reservedLPInvariant; @@ -85,11 +84,11 @@ contract VaultBorrowStrategy is VaultBaseRebalanceStrategy, BorrowStrategy { checkExpectedUtilizationRate(lpTokens, isRefType3); if(isRefType3) { - uint256 reservedLPTokens = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)); + uint256 reservedLPTokens = s.getUint256(RESERVED_LP_TOKENS()); unchecked { reservedLPTokens = reservedLPTokens - GSMath.min(reservedLPTokens, lpTokens); } - s.setUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS), reservedLPTokens); + s.setUint256(RESERVED_LP_TOKENS(), reservedLPTokens); } // Withdraw reserve tokens from CFMM that lpTokens represent @@ -102,8 +101,7 @@ contract VaultBorrowStrategy is VaultBaseRebalanceStrategy, BorrowStrategy { (liquidityBorrowed, loanLiquidity) = openLoan(_loan, lpTokens); if(isRefType3) { - uint256 reservedBorrowedInvariant = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_BORROWED_INVARIANT)); - s.setUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_BORROWED_INVARIANT), reservedBorrowedInvariant + liquidityBorrowed); + s.setUint256(RESERVED_BORROWED_INVARIANT(), s.getUint256(RESERVED_BORROWED_INVARIANT()) + liquidityBorrowed); } if(isRatioValid(ratio)) { diff --git a/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol b/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol index 91002cd..8c8cca2 100644 --- a/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol +++ b/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol @@ -58,18 +58,16 @@ contract VaultExternalRebalanceStrategy is VaultBaseLongStrategy, ExternalRebala checkExpectedUtilizationRate(lpTokens, true); - uint256 reservedLPTokens = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)); - - s.setUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS), reservedLPTokens + lpTokens); + s.setUint256(RESERVED_LP_TOKENS(), s.getUint256(RESERVED_LP_TOKENS()) + lpTokens); } else { - uint256 reservedLPTokens = s.getUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS)); + uint256 reservedLPTokens = s.getUint256(RESERVED_LP_TOKENS()); lpTokens = GSMath.min(reservedLPTokens, lpTokens); unchecked { reservedLPTokens = reservedLPTokens - lpTokens; } - s.setUint256(uint256(IVaultGammaPool.StorageIndexes.RESERVED_LP_TOKENS), reservedLPTokens); + s.setUint256(RESERVED_LP_TOKENS(), reservedLPTokens); } return lpTokens; diff --git a/contracts/test/TestVaultGammaPool.sol b/contracts/test/TestVaultGammaPool.sol new file mode 100644 index 0000000..5034674 --- /dev/null +++ b/contracts/test/TestVaultGammaPool.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.8.0; + +import "../pools/VaultGammaPool.sol"; + +contract TestVaultGammaPool is VaultGammaPool { + constructor(InitializationParams memory params) VaultGammaPool(params) { + } + + function getRESERVED_LP_TOKENS() external virtual pure returns(uint256) { + return RESERVED_LP_TOKENS(); + } + + function getRESERVED_BORROWED_INVARIANT() external virtual pure returns(uint256) { + return RESERVED_BORROWED_INVARIANT(); + } + + function reserveLPTokens(uint256 tokenId, uint256 lpTokens, bool isReserve) external virtual override returns(uint256) { + return 0; + } + + function validateCFMM(address[] calldata _tokens, address _cfmm, bytes calldata) external virtual override view returns(address[] memory) { + return new address[](0); + } +} diff --git a/contracts/test/strategies/vault/TestVaultBaseStrategy.sol b/contracts/test/strategies/vault/TestVaultBaseStrategy.sol new file mode 100644 index 0000000..9afc40c --- /dev/null +++ b/contracts/test/strategies/vault/TestVaultBaseStrategy.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.21; + +import "../../../strategies/vault/base/VaultBaseStrategy.sol"; + +contract TestVaultBaseStrategy is VaultBaseStrategy { + + constructor() { + } + + function getRESERVED_LP_TOKENS() external virtual pure returns(uint256) { + return RESERVED_LP_TOKENS(); + } + + function getRESERVED_BORROWED_INVARIANT() external virtual pure returns(uint256) { + return RESERVED_BORROWED_INVARIANT(); + } + + function calcBorrowRate(uint256 lpInvariant, uint256 borrowedInvariant, address paramsStore, address pool) public + virtual override view returns(uint256, uint256, uint256, uint256) { + return (0,0,0,0); + } + + function validateParameters(bytes calldata _data) external virtual override view returns(bool) { + return false; + } + + function syncCFMM(address cfmm) internal virtual override { + } + + function getReserves(address cfmm) internal virtual override view returns(uint128[] memory) { + return new uint128[](0); + } + + function getLPReserves(address cfmm, bool isLatest) internal virtual override view returns(uint128[] memory) { + return new uint128[](0); + } + + function calcInvariant(address cfmm, uint128[] memory amounts) internal virtual override view returns(uint256) { + return 0; + } + + function depositToCFMM(address cfmm, address to, uint256[] memory amounts) internal virtual override returns(uint256) { + return 0; + } + + function withdrawFromCFMM(address cfmm, address to, uint256 lpTokens) internal virtual override returns(uint256[] memory) { + return new uint256[](0); + } + + function maxTotalApy() internal virtual override view returns(uint256) { + return 0; + } + + function blocksPerYear() internal virtual override view returns(uint256) { + return 0; + } +} diff --git a/test/foundry/VaultGammaPool.t.sol b/test/foundry/VaultGammaPool.t.sol new file mode 100644 index 0000000..b46916a --- /dev/null +++ b/test/foundry/VaultGammaPool.t.sol @@ -0,0 +1,48 @@ +pragma solidity ^0.8.0; + +import "forge-std/Test.sol"; +import "../../contracts/test/TestVaultGammaPool.sol"; +import "../../contracts/test/strategies/vault/TestVaultBaseStrategy.sol"; + +contract VaultGammaPoolTest is Test { + + TestVaultGammaPool vaultPool; + TestVaultBaseStrategy vaultStrategy; + + function setUp() public { + ICPMMGammaPool.InitializationParams memory params = ICPMMGammaPool.InitializationParams({ + protocolId: 1, + factory: address(0), + borrowStrategy: address(0), + repayStrategy: address(0), + rebalanceStrategy: address(0), + shortStrategy: address(0), + liquidationStrategy: address(0), + batchLiquidationStrategy: address(0), + viewer: address(0), + externalRebalanceStrategy: address(0), + externalLiquidationStrategy: address(0), + cfmmFactory: address(0), + cfmmInitCodeHash: bytes32(0) + }); + + vaultPool = new TestVaultGammaPool(params); + vaultStrategy = new TestVaultBaseStrategy(); + } + + function testPoolRESERVED_BORROWED_INVARIANT() public { + assertEq(vaultPool.getRESERVED_BORROWED_INVARIANT(),uint256(keccak256("RESERVED_BORROWED_INVARIANT"))); + } + + function testPoolRESERVED_LP_TOKENS() public { + assertEq(vaultPool.getRESERVED_LP_TOKENS(),uint256(keccak256("RESERVED_LP_TOKENS"))); + } + + function testStrategyRESERVED_BORROWED_INVARIANT() public { + assertEq(vaultStrategy.getRESERVED_BORROWED_INVARIANT(),uint256(keccak256("RESERVED_BORROWED_INVARIANT"))); + } + + function testStrategyRESERVED_LP_TOKENS() public { + assertEq(vaultStrategy.getRESERVED_LP_TOKENS(),uint256(keccak256("RESERVED_LP_TOKENS"))); + } +} From 7fdbab55c54b17771862101da964106fdb6e62b8 Mon Sep 17 00:00:00 2001 From: danielalcarraz Date: Thu, 13 Mar 2025 16:00:33 -0400 Subject: [PATCH 2/3] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 95f9499..6b56fcf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gammaswap/v1-implementations", - "version": "1.2.16", + "version": "1.2.17", "description": "Pool and strategies implementation contracts for GammaSwap V1 protocol", "homepage": "https://gammaswap.com", "scripts": { From 7f10e1bc92f109f277a3d032f8f5fa124eda092a Mon Sep 17 00:00:00 2001 From: danielalcarraz Date: Thu, 13 Mar 2025 17:51:33 -0400 Subject: [PATCH 3/3] optimize calling hashed key functions --- .../strategies/vault/base/VaultBaseRepayStrategy.sol | 5 +++-- .../strategies/vault/lending/VaultBorrowStrategy.sol | 8 +++++--- .../vault/rebalance/VaultExternalRebalanceStrategy.sol | 7 ++++--- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol b/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol index ad9b813..5283afd 100644 --- a/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol +++ b/contracts/strategies/vault/base/VaultBaseRepayStrategy.sol @@ -77,12 +77,13 @@ abstract contract VaultBaseRepayStrategy is BaseRepayStrategy, VaultBaseRebalanc } if(_loan.refType == 3 && _paidLiquidity > 0) { - uint256 reservedBorrowedInvariant = s.getUint256(RESERVED_BORROWED_INVARIANT()); + uint256 key = RESERVED_BORROWED_INVARIANT(); + uint256 reservedBorrowedInvariant = s.getUint256(key); _paidLiquidity = GSMath.min(reservedBorrowedInvariant, _paidLiquidity); unchecked { reservedBorrowedInvariant = reservedBorrowedInvariant - _paidLiquidity; } - s.setUint256(RESERVED_BORROWED_INVARIANT(), reservedBorrowedInvariant); + s.setUint256(key, reservedBorrowedInvariant); } } } diff --git a/contracts/strategies/vault/lending/VaultBorrowStrategy.sol b/contracts/strategies/vault/lending/VaultBorrowStrategy.sol index 972937a..bc5d1c3 100644 --- a/contracts/strategies/vault/lending/VaultBorrowStrategy.sol +++ b/contracts/strategies/vault/lending/VaultBorrowStrategy.sol @@ -84,11 +84,12 @@ contract VaultBorrowStrategy is VaultBaseRebalanceStrategy, BorrowStrategy { checkExpectedUtilizationRate(lpTokens, isRefType3); if(isRefType3) { - uint256 reservedLPTokens = s.getUint256(RESERVED_LP_TOKENS()); + uint256 key = RESERVED_LP_TOKENS(); + uint256 reservedLPTokens = s.getUint256(key); unchecked { reservedLPTokens = reservedLPTokens - GSMath.min(reservedLPTokens, lpTokens); } - s.setUint256(RESERVED_LP_TOKENS(), reservedLPTokens); + s.setUint256(key, reservedLPTokens); } // Withdraw reserve tokens from CFMM that lpTokens represent @@ -101,7 +102,8 @@ contract VaultBorrowStrategy is VaultBaseRebalanceStrategy, BorrowStrategy { (liquidityBorrowed, loanLiquidity) = openLoan(_loan, lpTokens); if(isRefType3) { - s.setUint256(RESERVED_BORROWED_INVARIANT(), s.getUint256(RESERVED_BORROWED_INVARIANT()) + liquidityBorrowed); + uint256 key = RESERVED_BORROWED_INVARIANT(); + s.setUint256(key, s.getUint256(key) + liquidityBorrowed); } if(isRatioValid(ratio)) { diff --git a/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol b/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol index 8c8cca2..fc82bfc 100644 --- a/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol +++ b/contracts/strategies/vault/rebalance/VaultExternalRebalanceStrategy.sol @@ -50,6 +50,7 @@ contract VaultExternalRebalanceStrategy is VaultBaseLongStrategy, ExternalRebala updateLoan(_loan); + uint256 key = RESERVED_LP_TOKENS(); if(isReserve) { uint256 lpTokenBalance = getAdjLPTokenBalance(); @@ -58,16 +59,16 @@ contract VaultExternalRebalanceStrategy is VaultBaseLongStrategy, ExternalRebala checkExpectedUtilizationRate(lpTokens, true); - s.setUint256(RESERVED_LP_TOKENS(), s.getUint256(RESERVED_LP_TOKENS()) + lpTokens); + s.setUint256(key, s.getUint256(key) + lpTokens); } else { - uint256 reservedLPTokens = s.getUint256(RESERVED_LP_TOKENS()); + uint256 reservedLPTokens = s.getUint256(key); lpTokens = GSMath.min(reservedLPTokens, lpTokens); unchecked { reservedLPTokens = reservedLPTokens - lpTokens; } - s.setUint256(RESERVED_LP_TOKENS(), reservedLPTokens); + s.setUint256(key, reservedLPTokens); } return lpTokens;