Loud Snowy Marmot
High
L0ckin7 High
The _withdraw
and _deposit
functions transfer tokens before updating the internal state (_totalAssets
), this can lead to reentrancy attacks.
AutoCompoundingPodLp :
IERC20(_asset()).safeTransferFrom(_msgSender(), address(this), _assets);
This transfers tokens from the caller before updating _totalAssets
.
IERC20(_asset()).safeTransfer(_receiver, _assets);
This transfers tokens before reducing _totalAssets and burning shares.
Allow an attacker to manipulate the contract's state, such as withdrawing more tokens than they are entitled to.
If an attacker deposits a small amount to the contract then calls withdraw triggering _withdraw
, a malicious fallback function in the attacker's contract can re-enters _withdraw
before _totalAssets
and balances are updated, the attacker calls withdraw again draining funds before state updates.
We can use OpenZeppelin’s ReentrancyGuard
:
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract AutoCompoundingPodLp is IERC4626, ERC20, ERC20Permit, Ownable, ReentrancyGuard {
Then, add nonReentrant to _withdraw
and _deposit
:
function _deposit(uint256 _assets, uint256 _shares, address _receiver) internal nonReentrant {
function _withdraw(uint256 _assets, uint256 _shares, address _caller, address _owner, address _receiver) internal nonReentrant {
So we ensures state updates are completed before external calls, preventing reentrancy attacks.