Reentrancy prevention
Reentrancy prevention is a critical concept in the field of computer security and blockchain technology. It involves strategies and techniques designed to safeguard against potentially malicious or unintended recursive calls within a program or a smart contract. These recursive calls can pose a significant security risk, allowing attackers to exploit vulnerabilities and compromise the integrity of a system.
The simplest reentrancy prevention mechanism to use is the ReentrancyGuard
, which allows you to add a modifier, e.g. nonReentrant
, to functions which may otherwise be vulnerable. Although effective against most forms of reentrancy, it's important to understand how read-only reentrancy may be used to get around this and to always use the checks-effects-interactions pattern.
For optimum security, use the checks-effects-interactions pattern. This is a simple rule of thumb for ordering smart contract functions.
The function should begin with checks, e.g. require
and assert
statements.
Next, the effects of the contract should be performed, i.e. state modifications.
Finally, we can perform interactions with other smart contracts, e.g. external function calls.
This structure is effective against reentrancy because when an attacker reenters the function, the state changes have already been made. For example:
function withdraw() external {
uint256 amount = balances[msg.sender];
balances[msg.sender] = 0;
(bool success,) = msg.sender.call{value: balances[msg.sender]}("");
require(success);
}
Since the balance is set to 0 before any interactions are performed, if the contract is called recursively, there is nothing to send after the first transaction.