Assert Violation
Detects reachable assert() statements that indicate invariant violations and potential logic bugs in smart contracts.
Assert Violation
Overview
The assert violation detector identifies reachable assert() statements in smart contracts. Unlike require(), which validates external inputs, assert() checks internal invariants that should never be false. A reachable assertion failure means the contract’s own logic can reach a state the developer believed impossible — a strong indicator of bugs.
In Solidity versions before 0.8.0, a failed assert() emits the INVALID opcode (0xFE), consuming all remaining gas. In Solidity 0.8.0 and later, it emits a Panic(0x01) error code that still reverts but refunds unused gas.
Why This Is an Issue
A triggered assertion means the contract has entered a state that violates its own assumptions. Depending on what invariant is broken, this can lead to locked funds, incorrect state transitions, or denial of service. In pre-0.8 contracts, the gas-consuming INVALID opcode makes assertion failures particularly expensive for users, and attackers can exploit this for gas griefing.
How to Resolve
// Before: Reachable assertion — invariant can be violated
function withdraw(uint256 amount) external {
balances[msg.sender] -= amount;
assert(totalSupply >= amount); // Can fail if balances and totalSupply diverge
totalSupply -= amount;
payable(msg.sender).transfer(amount);
}
// After: Guard with require(), use assert() only for true invariants
function withdraw(uint256 amount) external {
require(balances[msg.sender] >= amount, "Insufficient balance");
require(totalSupply >= amount, "Supply underflow");
balances[msg.sender] -= amount;
totalSupply -= amount;
payable(msg.sender).transfer(amount);
assert(totalSupply == _computeExpectedSupply()); // True invariant check
}
Detection Methodology
- INVALID opcode scan: Identifies 0xFE bytes in pre-0.8 bytecode that correspond to failed
assert()calls. - Panic code detection: In 0.8+ bytecode, detects
Panic(0x01)revert patterns (selector0x4e487b71with code0x01). - Reachability analysis: Traces control flow to determine whether assert paths are reachable under valid inputs.
- Compiler version inference: Uses bytecode metadata to distinguish assert semantics between Solidity versions.
Limitations
False positives: Assertions that are theoretically reachable in the CFG but unreachable due to external constraints (e.g., token supply caps enforced by other contracts) may be flagged. False negatives: Custom assertion patterns that do not use the standard assert() built-in are not detected.
Related Detectors
- Unchecked Call — detects unchecked external call return values
- Business Logic Error — detects broader logic issues
- Division by Zero — detects Panic(0x12) division errors