Pattern Steps
- Check: Validate all conditions and requirements before making any state changes.
- Effect: Update the contract's state.
- Interaction: Interact with external contracts or send Ether.
Why use CEI?
- -Prevents reentrancy attacks by updating state before external calls.
- -Makes contracts easier to reason about and audit.
- -Encourages clear separation of logic.
Example
function withdraw(uint256 amount) public {
require(balances[msg.sender] >= amount, "Insufficient balance"); // Check
balances[msg.sender] -= amount; // Effect
(bool sent, ) = msg.sender.call{value: amount}(""); // Interaction
require(sent, "Failed to send Ether");
}