Analysis of the Barley Finance Exploit

5 min read

Learn how Barley Finance was exploited, resulting in a loss of assets worth $130,000.

TL;DR#

On January 28, 2024, Barley Finance was exploited on the Ethereum Mainnet due to a smart contract vulnerability, which resulted in a loss of assets worth approximately $130,000.

Introduction to Barley#

Barley Finance is a decentralized, permissionless, and trustless on-chain volatility farming protocol.

Vulnerability Assessment#

The root cause of the exploit is a lack of reentrancy protection.

The protocol was designed in such a way that the liquidity in the protocol could be recycled via flash loans, making it directly susceptible to flash-loan-based reentrancy attacks.

Steps#

Step 1:

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

Step 2:

The exploiter crafted their attack contract to take a flash loan of the entire BARL token from the vulnerable Wrapped Barley (wBARL) contract and trigger the callback of their deployed contract.

function flash(address _recipient, address _token, uint256 _amount, bytes calldata _data) external override {
  address _rewards = StakingPoolToken(lpStakingPool).poolRewards();
  IERC20(DAI).safeTransferFrom(_msgSender(), _rewards, FLASH_FEE_DAI * 10 ** IERC20Metadata(DAI).decimals());
  uint256 _balance = IERC20(_token).balanceOf(address(this));
  IERC20(_token).safeTransfer(_recipient, _amount);
  IFlashLoanRecipient(_recipient).callback(_data);
  require(IERC20(_token).balanceOf(address(this)) >= _balance, "FLASHAFTER");
  emit FlashLoan(_msgSender(), _recipient, _token, _amount);
}

Step 3:

Inside their callback, the attacker used the received BARL tokens to bond them back to the same wBARL contract to further receive the wBARL tokens.

function bond(address _token, uint256 _amount) external override noSwap {
  require(_isTokenInIndex[_token], "INVALIDTOKEN");
  uint256 _tokenIdx = _fundTokenIdx[_token];
  uint256 _tokensMinted = (_amount * FixedPoint96.Q96 * 10 ** decimals()) / indexTokens[_tokenIdx].q1;
  uint256 _feeTokens = _isFirstIn() ? 0 : (_tokensMinted * BOND_FEE) / 10000;
  _mint(_msgSender(), _tokensMinted - _feeTokens);
  if (_feeTokens > 0) {
    _mint(address(this), _feeTokens);
  }
  for (uint256 _i; _i < indexTokens.length; _i++) {
    uint256 _transferAmount = _i == _tokenIdx
      ? _amount
      : (_amount * indexTokens[_i].weighting * 10 ** IERC20Metadata(indexTokens[_i].token).decimals()) / indexTokens[_tokenIdx].weighting / 10 ** IERC20Metadata(_token).decimals();
    _transferAndValidate(IERC20(indexTokens[_i].token), _msgSender(), _transferAmount);
  }
  emit Bond(_msgSender(), _token, _amount, _tokensMinted);
}

Step 4:

The wBARL contract, as part of this bonding, pulls the BARL tokens from the attacker and is fooled into believing that it has received the repayment of the initially taken flash loan.

Step 5:

In essence, this attacker was able to freely mint the wBARL tokens, which they again de-bonded to get back the BARL from the index contract.

function debond(uint256 _amount, address[] memory, uint8[] memory) external override noSwap {
  uint256 _amountAfterFee = _isLastOut(_amount) ? _amount : (_amount * (10000 - DEBOND_FEE)) / 10000;
  uint256 _percAfterFeeX96 = (_amountAfterFee * FixedPoint96.Q96) / totalSupply();
  _transfer(_msgSender(), address(this), _amount);
  _burn(address(this), _amountAfterFee);
  for (uint256 _i; _i < indexTokens.length; _i++) {
    uint256 _tokenSupply = IERC20(indexTokens[_i].token).balanceOf(address(this));
    uint256 _debondAmount = (_tokenSupply * _percAfterFeeX96) / FixedPoint96.Q96;
    IERC20(indexTokens[_i].token).safeTransfer(_msgSender(), _debondAmount);
    require(IERC20(indexTokens[_i].token).balanceOf(address(this)) >= _tokenSupply - _debondAmount, "HEAVY");
  }
  emit Debond(_msgSender(), _amount);
}

Step 6:

The obtained BARL tokens were dumped into the BARL/DAI pool to be exchanged for DAI. These processes were repeated a few times to take away all of the remaining assets from the pool.

Step 7:

The exploiter was thus able to take away more than 10% of the total BARL supply in the pod, causing significant damage to the protocol.

Aftermath#

At the time of this writing, the protocol has already shut down their front-end application, and their social media channels have also been deleted. It can therefore be speculated that the ill intention of the team behind the development of the project. The vulnerable and exploited contract was deployed on January 26, 2024, two days before the occurrence of the exploit.

The exploited pool was capitalized with just one indexed asset, which most likely came from the core team. Given the limited number of transaction interactions, the incident could have also been initiated by a team member who was able to identify and exploit the bug. Jotting down the dots, one can claim that the protocol could have executed a sophisticated rug pull as well.

Solution#

To mitigate vulnerabilities like those exploited in Barley Finance, smart contract developers need to implement rigorous security measures. Reentrancy attacks have been central to many smart contract vulnerabilities historically. A highly recommended method to thwart such attacks is the Checks-Effects-Interactions (CEI) pattern. This approach suggests that developers should save all external interactions or calls for the final part of the function, making sure that operations altering the state happen before any external call. Additionally, employing a mutex lock or a binary semaphore can serve as a robust defense against reentrancy. By securing a function at the start and unlocking it just before finishing, it's possible to prevent the function from being called again before the initial call is fully executed, thus removing the risk of simultaneous calls.

For protocols that utilize flash loans for liquidity provisioning, it's important to validate the integrity of transactions and enforce checks that prevent the misuse of borrowed assets within the same transaction. By establishing strict guidelines and checks for the flow of assets, protocols can significantly reduce the risk of exploitation.

In the wake of incidents where projects suddenly shut down operations and erase their digital footprint, as speculated with Barley Finance, it highlights the need for investors to conduct thorough due diligence before investing in any project. This includes researching the project's development team, understanding the project's codebase by reviewing available audits, and engaging with the community to gauge the project's reputation. Platforms that offer decentralized finance services should also strive for transparency, regularly publish updates and audit results, and maintain open lines of communication with their users.

Even with strict security measures in place, the risk of vulnerabilities being exploited remains. In these situations, the significance of Neptune Mutual becomes critical. By setting up a dedicated cover pool with Neptune Mutual, the negative impacts of such incidents can be considerably reduced. We are experts in offering protection against losses stemming from smart contract vulnerabilities, using parametric policies designed for these particular risks.

Working with Neptune Mutual makes the process of recovery smoother for users by eliminating the requirement for extensive loss documentation. Following the confirmation and definitive resolution of an incident through our comprehensive incident resolution framework, we prioritize swift compensation and financial support for those impacted. This method guarantees quick aid for individuals affected by these security lapses.

Our services are available across various leading blockchain platforms, including EthereumArbitrum, and the BNB chain, serving a broad spectrum of DeFi users. Our extensive network enables us to provide safeguards against a multitude of vulnerabilities, boosting security for our varied clientele.

Reference Source BlockSec

By

Tags