Omniscia Steadefi Audit

GMXPerpetualDEXLongManager Code Style Findings

GMXPerpetualDEXLongManager Code Style Findings

GMD-01C: Inefficient Code Repetition

TypeSeverityLocation
Gas OptimizationGMXPerpetualDEXLongManager.sol:L111-L123

Description:

The referenced lines of code are executed by the GMXPerpetualDEXLongManager::getTotalUsdgAmount function.

Example:

contracts/vaults/gmx/GMXPerpetualDEXLongManager.sol
110function currentTokenWeight(address _token) public view returns (uint256) {
111 uint256 length = gmxVault.allWhitelistedTokensLength();
112 uint256 usdgSupply;
113
114 address whitelistedToken;
115 bool isWhitelisted;
116
117 for (uint256 i = 0; i < length; i++) {
118 whitelistedToken = gmxVault.allWhitelistedTokens(i);
119 isWhitelisted = gmxVault.whitelistedTokens(whitelistedToken);
120 if (isWhitelisted) {
121 usdgSupply += gmxVault.usdgAmounts(whitelistedToken);
122 }
123 }
124 return gmxVault.usdgAmounts(_token) * SAFE_MULTIPLIER / usdgSupply;
125}

Recommendation:

We advise the function to be invoked within GMXPerpetualDEXLongManager::currentTokenWeight, optimizing its execution cost.

Alleviation (4325253d6de0ea91c1e9fb9e01d2e7e98f3d83a9):

The latest code block of GMXPerpetualDEXLongManager::currentTokenWeight correctly invokes GMXPerpetualDEXLongManager::getTotalUsdgAmount minimizing its bytecode size.

GMD-02C: Inefficient Token Weight Assessment

TypeSeverityLocation
Gas OptimizationGMXPerpetualDEXLongManager.sol:L185

Description:

The GMXPerpetualDEXLongManager::assetInfo function calculates the total USDG supply and then proceeds to re-calculate it on each GMXPerpetualDEXLongManager::currentTokenWeight invocation it performs.

Example:

contracts/vaults/gmx/GMXPerpetualDEXLongManager.sol
161// get total supply of USDG
162uint256 usdgSupply = getTotalUsdgAmount();
163
164// calculate manager's glp amt in USDG
165uint256 glpAmtInUsdg = (lpTokenBal * SAFE_MULTIPLIER /
166 glpTotalSupply)
167 * usdgSupply
168 / SAFE_MULTIPLIER;
169
170uint256 length = gmxVault.allWhitelistedTokensLength();
171address[] memory tokenAddress = new address[](length);
172uint256[] memory tokenAmt = new uint256[](length);
173
174address whitelistedToken;
175bool isWhitelisted;
176uint256 tokenWeight;
177
178for (uint256 i = 0; i < length; i++) {
179 // check if token is whitelisted
180 whitelistedToken = gmxVault.allWhitelistedTokens(i);
181 isWhitelisted = gmxVault.whitelistedTokens(whitelistedToken);
182 if (isWhitelisted) {
183 tokenAddress[i] = whitelistedToken;
184 // calculate token weight expressed in token amt
185 tokenWeight = currentTokenWeight(whitelistedToken);

Recommendation:

We advise the code to instead assess the current token weight of a whitelisted token directly by replicating the calculation of GMXPerpetualDEXLongManager::currentTokenWeight with the usdgSupply local variable.

Alleviation (7c9b2b09dbe1f75d8c5ad379e658030ecf1be3a0):

The code has been optimized as advised, making use of the local usdgSupply variable and significantly reducing the gas cost of the referenced function.

GMD-03C: Loop Iterator Optimizations

TypeSeverityLocation
Gas OptimizationGMXPerpetualDEXLongManager.sol:L117, L142, L178, L209

Description:

The linked for loops increment / decrement their iterator "safely" due to Solidity's built - in safe arithmetics(post - 0.8.X).

Example:

contracts/vaults/gmx/GMXPerpetualDEXLongManager.sol
117for (uint256 i = 0; i < length; i++) {

Recommendation:

We advise the increment / decrement operations to be performed in an unchecked code block as the last statement within each for loop to optimize their execution cost.

Alleviation (4325253d6de0ea91c1e9fb9e01d2e7e98f3d83a9):

All iterator increment statements have been relocated to unchecked code blocks at the end of each respective for loop's body, optimizing their gas cost.

GMD-04C: Repetition of Statements

TypeSeverityLocation
Gas OptimizationGMXPerpetualDEXLongManager.sol:L235-L240, L257-L262

Description:

The ManagerAction.Deposit and ManagerAction.AddLiquidity flows are identical within GMXPerpetualDEXLongManager::work.

Example:

contracts/vaults/gmx/GMXPerpetualDEXLongManager.sol
234// ********** Deposit Flow **********
235if (_action == ManagerAction.Deposit) {
236 // borrow from lending pool
237 _borrow(_borrowTokenAmt);
238 // add tokens to LP receive LP tokens and stake
239 _addLiquidity();
240}
241
242// ********** Withdraw Flow **********
243if (_action == ManagerAction.Withdraw) {
244 if (_lpAmt > 0) {
245 // If estimated LP amount is more than actual LP amount owned
246 if (_lpAmt > lpTokenAmt()) {
247 _lpAmt = lpTokenAmt();
248 }
249 // remove LP receive token
250 _removeLiquidity(_lpAmt);
251 // repay lending pool
252 _repay(_repayTokenAmt);
253 }
254}
255
256// ********** Rebalance: Add Liquidity Flow **********
257if (_action == ManagerAction.AddLiquidity) {
258 // Borrow from lending pool
259 _borrow(_borrowTokenAmt);
260 // Add tokens to lp receive lp tokens
261 _addLiquidity();
262}

Recommendation:

We advise their conditionals to be merged with an else (||) clause, optimizing the codebase.

Alleviation (4325253d6de0ea91c1e9fb9e01d2e7e98f3d83a9):

The code branches of ManagerAction.AddLiquidity and ManagerAction.Deposit have been merged to the same if block as per our recommendation.

GMD-05C: Variable Mutability Specifiers (Immutable)

TypeSeverityLocation
Gas OptimizationGMXPerpetualDEXLongManager.sol:L64-L71

Description:

The linked variables are assigned to only once during the contract's constructor.

Example:

contracts/vaults/gmx/GMXPerpetualDEXLongManager.sol
54constructor(
55 IGMXPerpetualDEXLongVault _vault,
56 ILendingPool _tokenLendingPool,
57 IGMXRewardRouterHandler _rewardRouterHandler,
58 IGMXRewardRouter _rewardRouter,
59 IGMXStakePool _stakePool,
60 IGMXGLPManager _glpManager,
61 IGMXRewardReader _rewardReader,
62 IGMXVault _gmxVault
63) {
64 vault = _vault;
65 tokenLendingPool = _tokenLendingPool;
66 rewardRouterHandler = _rewardRouterHandler;
67 rewardRouter = _rewardRouter;
68 stakePool = _stakePool;
69 glpManager = _glpManager;
70 rewardReader = _rewardReader;
71 gmxVault = _gmxVault;
72 IERC20(rewardRouter.weth()).approve(address(glpManager), type(uint256).max);
73 IERC20(token()).approve(address(glpManager), type(uint256).max);
74 IERC20(token()).approve(address(tokenLendingPool), type(uint256).max);
75}

Recommendation:

We advise them to be set as immutable greatly optimizing their read-access gas cost.

Alleviation (4325253d6de0ea91c1e9fb9e01d2e7e98f3d83a9):

All variables have been set as immutable per our recommendation, greatly reducing their read-access gas cost.