Assessment reports>Lido Fixed Income>Critical findings>Fixed depositor reentrancy can take all the ETH
Category: Coding Mistakes

Fixed depositor reentrancy can take all the ETH

Critical Severity
Critical Impact
High Likelihood

Description

After a vault begins, fixed depositors can call the claimFixedPremium() function to claim their ETH fixed premium:

function claimFixedPremium() external {
  require(isStarted(), "CBS");

  // Check and cache balance for gas savings
  uint256 claimBal = fixedClaimToken[msg.sender];
  require(claimBal > 0, "NCT");

  // Send a proportional share of the total variable side deposits (premium) to the fixed side depositor
  uint256 sendAmount = fixedETHDepositToken[msg.sender].mulDiv(variableSideCapacity, fixedSideCapacity);

  // Track premiums
  userToFixedUpfrontPremium[msg.sender] = sendAmount;

  (bool sent, ) = msg.sender.call{value: sendAmount}("");
  require(sent, "ETF");

  // Mint bearer token
  fixedBearerToken[msg.sender] += claimBal;
  fixedBearerTokenTotalSupply += claimBal;

  // Burn claim tokens
  fixedClaimToken[msg.sender] = 0;
  fixedClaimTokenTotalSupply -= claimBal;

  emit FixedPremiumClaimed(sendAmount, claimBal, msg.sender);
}

However, since the ETH is sent before the burning of the claim tokens, if the call to msg.sender reenters the same function, the user can claim their fixed premium again and again.

Impact

Any fixed depositor can reenter claimFixedPremium() as many times as the gas and stack-size limit permit. By ensuring that their initial deposit is an even multiple of their claim, they can drain the entire balance using this reentrancy attack.

Additionally, this inflates the user's fixedBearerToken, which causes them to be able to claim more of the returned fixed principal than they deserve after the vault ends.

Recommendations

Send the sendAmount to the caller after the claim tokens are burned.

Remediation

This issue has been acknowledged by Saffron, and a fix was implemented in commit 0b1fbc2d.

Zellic © 2024Back to top ↑