How Was Gamma Protocol Exploited?

6 min read

Learn how the Gamma Protocol was exploited, resulting in a loss of $4.6 million.

TL;DR#

On January 4, 2024, the Gamma Protocol was exploited on the Arbitrum Chain due to a smart contract vulnerability, which resulted in a loss of over 1,500 ETH worth approximately $4.6 million.

Introduction to Gamma#

Gamma is a protocol designed for non-custodial, automated, and active management of concentrated liquidity.

Vulnerability Assessment#

The root cause of the exploit is due to the price manipulation of the underlying assets.

Steps#

Step 1:

We attempt to analyze one of the attack transactions executed by the exploiter.

Step 2:

The exploit was entirely vested in the Hypervisor contract of Gamma Strategies. In the deposit function of this contract, the `shares` value is calculated based on the provided `deposit0` and `deposit1` amounts and the calculated price, which means it takes into account both the token amounts into a single share value.

/// @notice Deposit tokens
/// @param deposit0 Amount of token0 transfered from sender to Hypervisor
/// @param deposit1 Amount of token1 transfered from sender to Hypervisor
/// @param to Address to which liquidity tokens are minted
/// @param from Address from which asset tokens are transferred
/// @param inMin min spend for directDeposit is true
/// @return shares Quantity of liquidity tokens minted as a result of deposit
function deposit(uint256 deposit0, uint256 deposit1, address to, address from, uint256[4] memory inMin) external nonReentrant returns (uint256 shares) {
  require(deposit0 > 0 || deposit1 > 0);
  require(deposit0 <= deposit0Max && deposit1 <= deposit1Max);
  require(to != address(0) && to != address(this), "to");
  require(msg.sender == whitelistedAddress, "WHE");

  /// update fees
  zeroBurn();

  (uint160 sqrtPrice, , , , , , , ) = pool.globalState();
  uint256 price = FullMath.mulDiv(uint256(sqrtPrice).mul(uint256(sqrtPrice)), PRECISION, 2 ** (96 * 2));

  (uint256 pool0, uint256 pool1) = getTotalAmounts();

  shares = deposit1.add(deposit0.mul(price).div(PRECISION));

  if (deposit0 > 0) {
    token0.safeTransferFrom(from, address(this), deposit0);
  }
  if (deposit1 > 0) {
    token1.safeTransferFrom(from, address(this), deposit1);
  }

  uint256 total = totalSupply();
  if (total != 0) {
    uint256 pool0PricedInToken1 = pool0.mul(price).div(PRECISION);
    shares = shares.mul(total).div(pool0PricedInToken1.add(pool1));
    if (directDeposit) {
      uint128 liquidity = _liquidityForAmounts(baseLower, baseUpper, token0.balanceOf(address(this)), token1.balanceOf(address(this)));
      _mintLiquidity(baseLower, baseUpper, liquidity, address(this), inMin[0], inMin[1]);
      liquidity = _liquidityForAmounts(limitLower, limitUpper, token0.balanceOf(address(this)), token1.balanceOf(address(this)));
      _mintLiquidity(limitLower, limitUpper, liquidity, address(this), inMin[2], inMin[3]);
    }
  }
  _mint(to, shares);
  emit Deposit(from, to, shares, deposit0, deposit1);
  /// Check total supply cap not exceeded. A value of 0 means no limit.
  require(maxTotalSupply == 0 || total <= maxTotalSupply, "max");
}

Step 3:

The exploiter first performed a large value swap to manipulate and pump the price of USDC.e in the pool.

Step 4:

The exploiter then called the above deposit function of the contract with these large input assets, which were used to calculate the share amount but not for adding liquidity.

As these tokens were left in the contract itself as a result of the manipulated token price, they were subsequently used in the next deposit cycle.

Step 5:

The withdrawal process removed liquidity from both the base and limit positions. As the hacker owned the liquidity in the base position, they were able to receive more tokens than what they had deposited.

Step 6:

The next deposit cycle made use of the USDC.e left over in the earlier steps to add liquidity to the base position, which was later withdrawn. These steps were repeated over and over again before converting all parts of the proceeds to ETH.

Despite four deposit protection measures, the attack was viable due to the broad range of allowed price changes within certain vaults.

Step 7:

At the time of this writing, the stolen assets worth $4,192,922 were held at this address, with $2,962,387 held on the Ethereum Mainnet and $1,230,534 on the Arbitrum chain. The attacker has already laundered 1000 ETH, worth approximately $2,269,470, to Tornado Cash.

Aftermath#

The team acknowledged the occurrence of the exploit and stated that they are working on monitoring and isolating the incident. A later update by the team stated that all public vaults and hypervisors that had deposits were shut down. These vaults will continue to be managed normally for now, but deposits are currently shut down until they completely identify and mitigate the problem.

The team stated that there were four main sources of deposit protection against flash loan attacks: mandating a ratio of token0 and token1 in accordance with the ratio in the pool, setting a price change threshold, setting deposit caps per deposit, and disallowing single-sided deposits.

However, the price change threshold, at which deposits should have been disallowed when the price exceeded a range, was set too high, allowing for up to 50–200% variation on certain LST and stable coin vaults. This allowed the attacker to manipulate the price up to the price change threshold and mint a disproportionately high number of LP tokens.

Solution#

To address the exploit in the Gamma Protocol, a comprehensive and multi-faceted approach is necessary to enhance security and safeguard user assets.

A critical initial step involves conducting an exhaustive code review and security audit of all smart contracts within the protocol. The primary focus during this review will be on the identification and rectification of vulnerabilities related to price manipulation, asset calculations, and token transfers. By conducting a thorough examination, potential weaknesses can be identified and rectified proactively, mitigating the risk of future exploits.

Furthermore, the implementation of a dependable and decentralized price oracle solution is imperative. This oracle will serve to furnish accurate and tamper-proof price data for assets within the protocol. By relying on such a trusted source of price information, the risk associated with manipulated price feeds is substantially reduced. A key aspect here is ensuring that the price change threshold is set to a viable level. This threshold should be carefully calibrated to allow for reasonable price variations while preventing excessive manipulation. Striking the right balance is essential to the protocol's security.

In addition to these proactive measures, periodic security audits by independent third-party firms should be instituted as an ongoing practice. These audits will serve to continually evaluate the protocol's security posture and pinpoint potential vulnerabilities. Engaging independent auditors provides an additional layer of protection against emerging security threats.

However, it is crucial to acknowledge that even with the implementation of stringent security measures, vulnerabilities may still be exploited. This highlights the vital role that Neptune Mutual plays in the DeFi ecosystem. In the unfortunate event of security breaches or incidents, the establishment of a dedicated cover pool with Neptune Mutual could have significantly alleviated the consequences of the Gamma Protocol exploit. Neptune Mutual offers comprehensive coverage to users who suffer losses of funds or digital assets due to smart contract vulnerabilities, thanks to its parametric policies.

Collaborating with Neptune Mutual eliminates the need for users to navigate the often intricate process of providing detailed proof of loss. Once an incident has been verified and resolved through our robust incident resolution framework, the protocol prioritizes the swift disbursement of compensation. This ensures immediate financial relief for those affected, underscoring the critical role played by Neptune Mutual in supporting and safeguarding the DeFi community.

Neptune Mutual extends its operations across various prominent blockchain networks, including EthereumArbitrum, and the BNB chain. This expansive presence enables us to cater to a diverse spectrum of DeFi users, offering them protection against potential vulnerabilities and reinforcing their trust in the ecosystem.

Reference Source Gamma

By

Tags