Solidity Security: Mitigating Smart Contract Reentrancy Attacks
Solidity Security: Defeating Smart Contract Reentrancy
In decentralized finance (DeFi), reentrancy represents the most destructive smart contract vulnerability, leading to multi-million dollar drainage of token staking pools.
The Reentrancy Exploit Flow
Reentrancy happens when a smart contract executes an external call (e.g. sending Ether to an untrusted address) before updating its internal ledger state.
// VULNERABLE METHOD
function withdraw() public {
uint amount = balances[msg.sender];
(bool success, ) = msg.sender.call{value: amount}(""); // External call
require(success);
balances[msg.sender] = 0; // State update after external call!
}
An attacker contracts a fallback function that calls withdraw() again when receiving the transaction. Because the balance has not been set to 0, the withdrawal executes repeatedly, draining the contract pool.
Mitigations
1. Checks-Effects-Interactions Pattern
Always update states before triggering interactions with external contracts:
function withdrawPatched() public {
uint amount = balances[msg.sender];
balances[msg.sender] = 0; // Update state FIRST (Effect)
(bool success, ) = msg.sender.call{value: amount}(""); // Interaction LAST
require(success);
}
2. Use ReentrancyGuard
Import and inherit OpenZeppelin's ReentrancyGuard, utilizing the nonReentrant modifier for withdrawal functions.
Secure Your SaaS Assets Today
Ready to perform a deep-dive manual logical security audit? Schedule a scoping review with our lead architects.