DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: low
Invalid

Missing Adherence to Check-Effects-Interaction Pattern in State Updates( Fertilizer.sol))

Summary

The Fertilizer.sol contract has functions that do not follow the best practice of check-effects-interaction. This can lead to reentrancy vulnerabilities. Specifically, state variables are updated after external calls, which can introduce a security risk.

Vulnerability Details

In the Fertilizer.sol contract, the functions _balances[id][account].lastBpf = bpf; and _balances[ids[i]][account].lastBpf = uint128(stopBpf); update state variables after making external calls. This practice can lead to reentrancy vulnerabilities where an external contract might exploit the contract's state before the state updates are finalized.

Line 58

_balances[id][account].lastBpf = bpf;

Line 90

_balances[id][account].lastBpf = bpf;

Impact

Not following the check-effects-interaction pattern can lead to reentrancy attacks, where an external contract can repeatedly call back into the vulnerable function, manipulating the state in ways not intended by the original contract logic. This can lead to loss of funds, unauthorized state changes, or other critical issues.

Tools Used

Manual code review

Recommendations

To mitigate these risks, ensure that state updates are made before any external calls. Here are the updated snippets following the check-effects-interaction pattern:

Updated _update Function

function _update(address account, uint256[] memory ids, uint256 bpf) internal {
uint256 amount = __update(account, ids, bpf);
if (amount > 0) {
// State update before external call
+ _balances[id][account].lastBpf = uint128(stopBpf);
+ IBS(owner()).payFertilizer(account, amount);
}
}

Updated __update Function

function __update(
address account,
uint256[] memory ids,
uint256 bpf
) internal returns (uint256 beans) {
for (uint256 i; i < ids.length; ++i) {
uint256 stopBpf = bpf < ids[i] ? bpf : ids[i];
uint256 deltaBpf = stopBpf - _balances[ids[i]][account].lastBpf;
if (deltaBpf > 0) {
// State update before external call
+ _balances[ids[i]][account].lastBpf = uint128(stopBpf);
+ beans = beans.add(deltaBpf.mul(_balances[ids[i]][account].amount));
}
}
emit ClaimFertilizer(ids, beans);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Too generic

Support

FAQs

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