Omniscia Gamma Strategies Audit

GammaController Code Style Findings

GammaController Code Style Findings

GCR-01C: Data Location Optimization

Description:

The linked variable is declared as memory in an external function.

Example:

contracts/adapters/tokemak/GammaController.sol
61function withdraw(
62 address lpTokenAddress,
63 uint256 amount,
64 uint256[N_COINS] memory minAmounts
65) external onlyManager {

Recommendation:

We advise it to be set as calldata optimizing the codebase.

Alleviation:

The Gamma Strategies team considered this exhibit but opted not to apply a remediation for it in the current iteration of the codebase.

GCR-02C: Ineffectual Extraneous Approval Logic

Description:

The _approve function of the contract performs multiple contract calls redundantly as the chain of operations it performs results in the same state as a single approve call would.

Example:

contracts/adapters/tokemak/GammaController.sol
99function _approve(
100 IERC20 token,
101 address spender,
102 uint256 amount
103) internal {
104 uint256 currentAllowance = token.allowance(address(this), spender);
105 if (currentAllowance > 0) {
106 token.safeDecreaseAllowance(spender, currentAllowance);
107 }
108 token.safeIncreaseAllowance(spender, amount);
109}

Recommendation:

We advise the approve function to be utilized directly as the code currently reads the allowance, sets it to zero if it is positive and then re-sets it to the new value essentially overwriting it which is the exact behaviour of approve.

Alleviation:

The Gamma Strategies team considered this exhibit and acknowledged the gas optimization it achieves, however, they wish to support non-standard tokens such as USDT which require the allowance to be set to zero prior to a non-zero value and as such, we consider this optimization nullified.

GCR-03C: Ineffectual Hypervisor Allowance Integration

Description:

The deploy function will approve the Hypervisor with the balances it is meant to extract, however, the allowance is ineffectual in case the manager set during construction is not the contract itself.

Example:

contracts/adapters/tokemak/GammaController.sol
42// approve Hypervisor to spend amount0,1 amounts of Hypervisor.token0,1
43_approve(ITokeHypervisor(lpTokenAddress).token0(), lpTokenAddress, amount0);
44_approve(ITokeHypervisor(lpTokenAddress).token1(), lpTokenAddress, amount1);
45
46uint256 lpTokenBalanceBefore = IERC20(lpTokenAddress).balanceOf(manager);
47// deposit amount0, amount1 and mint LP tokens to the manager
48// uint256 lpTokenReceived = uniProxy.deposit(amount0, amount1, manager, lpTokenAddress);
49uint256 lpTokenReceived = ITokeHypervisor(lpTokenAddress).deposit(amount0, amount1, manager, manager);

Recommendation:

We advise the allowance operations to be omitted from the codebase as the deposit function of ITokeHypervisor will pull the tokens from the manager rather than the caller.

Alleviation:

The Gamma Strategies team considered this exhibit and stated that in an operational context they expect the manager account to utilize delegateCall to interact with the contract on the deploy function and as such the msg.sender will be the address(this) member for the approval rendering it valid. As a result, we consider this exhibit nullified.