Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: high
Invalid

Reentrancy vulnerability in function withdraw(2024-09-stakelink/contracts/core /InsurancePool.sol)

Summary:

A reentrancy vulnerability occurs when a smart contract allows an external contract to call back into the original function before its initial execution is completed. This allows the attacker to repeatedly trigger certain actions, such as withdrawing funds, potentially draining the contract of its balance. In this report, we will explore how the vulnerability was identified and detail its impact, the tools used, and recommendations for mitigation.

Vulnerability Details:

The reentrancy vulnerability was found in the withdraw function of the smart contract. The issue arises because the function performs an external call (sending Ether or tokens to the caller) before updating the contract’s internal state (specifically the user's balance). This creates an opportunity for an attacker to repeatedly call the withdraw function before the contract’s state is updated, allowing them to drain funds multiple times in a single transaction.

function withdraw(uint256 _amount) external whileNoClaimInProgress {
if (!canWithdraw(msg.sender)) revert WithdrawalWindowInactive();
rewardsPool.updateReward(msg.sender);
_burn(msg.sender, _amount);
totalDeposits -= _amount;
token.safeTransfer(msg.sender, _amount);
}

How the Attack Works:

  1. The withdraw function allows a user to withdraw funds from the contract.

  2. The contract makes an external call to msg.sender using .call, sending the requested amount before reducing the user’s balance.

  3. An attacker can exploit this by creating a fallback function in their contract, which re-calls the vulnerable withdraw function.

  4. Since the contract has not yet updated the attacker’s balance, each reentrant call to withdraw will succeed, allowing the attacker to drain the contract of its funds in a recursive loop.

Impact :

A reentrancy vulnerability in an InsurancePool contract could allow an attacker to repeatedly withdraw funds or claim payouts before the contract updates its internal state. This could lead to complete depletion of the pool's funds, preventing legitimate users from receiving their claims, resulting in financial loss, loss of trust, and potential legal consequences for the platform.

Tools Used :

1) Remix (AI)
2) Manually & Phind AI Serach Engine & Claude Search Engine

Recommendations:

Reentrancy Vulnerability: The original withdraw() function was vulnerable to reentrancy attacks. I've added the nonReentrant modifier from OpenZeppelin's ReentrancyGuard to prevent this.

/**
* @notice withdraws tokens from the pool
* @param _amount amount of tokens to withdraw
*/
function withdraw(uint256 _amount) external nonReentrant whileNoClaimInProgress {
require(_amount > 0, "Withdraw amount must be greater than 0");
require(canWithdraw(msg.sender), "Withdrawal window inactive");
rewardsPool.updateReward(msg.sender);
_burn(msg.sender, _amount);
totalDeposits = totalDeposits.sub(_amount);
token.safeTransfer(msg.sender, _amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.