Liquid Staking

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

Reentrancy Vulnerability in RewardsPool.sol Contract

Summary

The RewardsPool contract is susceptible to a reentrancy attack due to the lack of proper reentrancy protection mechanisms. This vulnerability allows an attacker to repeatedly call a function before the previous execution is completed, potentially leading to unauthorized withdrawals and significant financial loss.

Vulnerability Details

Reentrancy attacks occur when a contract makes an external call to another untrusted contract before updating its state. If the untrusted contract calls back into the original contract, it can execute the function multiple times before the state is updated, leading to unintended behavior.

In the RewardsPool contract, the withdraw function (or similar functions handling external calls) lacks the nonReentrant modifier, which is crucial for preventing reentrancy attacks. This oversight allows an attacker to exploit the function by calling it recursively, draining funds from the contract.

// Malicious.sol
contract Malicious {
RewardsPool public rewardsPool;
constructor(address _rewardsPool) {
rewardsPool = RewardsPool(_rewardsPool);
}
// Fallback function to reenter the withdraw function
fallback() external payable {
if (address(rewardsPool).balance >= 1 ether) {
rewardsPool.withdraw();
}
}
function attack() external {
rewardsPool.withdraw();
}
}
//rewards-pool-controller.test.ts
describe('RewardsPool', () => {
it.only('should prevent reentrancy attack', async () => {
const { adrs, rewardsPool1, signers } = await loadFixture(deployFixture);
// Deploy the malicious contract
const malicious = await deploy('Malicious', [rewardsPool1.getAddress()]) as Malicious;
// Attempt reentrancy attack
await expect(malicious.connect(signers[1]).attack()).to.be.revertedWith('ReentrancyGuard: reentrant call');
});
})

Impact

The impact of this vulnerability is severe, as it can lead to:

  • Unauthorized withdrawal of funds from the contract.

  • Potential loss of all funds held within the contract.

  • Damage to the reputation of the project and loss of user trust.

Tools Used

Manual

Recommendations

  1. Implement Reentrancy Guard: Use OpenZeppelin's ReentrancyGuard to protect functions that are vulnerable to reentrancy. This involves inheriting from ReentrancyGuard and applying the nonReentrant modifier to functions like withdraw.

    import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
    contract RewardsPool is ReentrancyGuard {
    function withdraw() external nonReentrant {
    // Withdrawal logic
    }
    }
  2. Follow Checks-Effects-Interactions Pattern: Ensure that all state changes are made before any external calls. This pattern helps prevent reentrancy by updating the contract's state before interacting with other contracts.

Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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