Requirement Violations Exploit Generator
Sigvex exploit generator that validates requirement violation findings by classifying the specific check failure — incorrect comparison, missing validation, assert misuse, or arithmetic overflow — and documenting the exploit path.
Requirement Violations Exploit Generator
Overview
The requirement violations exploit generator validates findings from the requirement_violations, missing_require, assertion_failure, and related detectors by classifying the specific type of requirement violation from the finding description and generating documentation of the exploit path it creates. The generator handles four violation categories: incorrect comparisons, missing validations, assert misuse, and missing arithmetic checks.
Requirement violations are often subtle — a <= where < was intended, a missing zero-check on a division denominator, or an assert used where require was intended. Each creates a different class of exploitable behavior: arithmetic overflows silently wrap in Solidity 0.7.x and below, missing validations allow forbidden state transitions, and assert misuse causes permanent state corruption on expected failure conditions.
Note: Exploit generation in Sigvex is for vulnerability validation purposes only.
Attack Scenario
Incorrect comparison:
- A contract uses
require(amount <= balance)instead ofrequire(amount < balance). - An attacker withdraws exactly
balance— draining the contract to zero. - Any subsequent users find the contract empty, including fees or reserves that should have been protected.
Missing validation:
- A function performs a division:
result = total / shares. - No check ensures
shares > 0. - When
shares == 0(e.g., during initial deployment or after all shares are burned), the division reverts unexpectedly. - Alternatively, if the context is a ratio or rate calculation, a zero denominator allows misuse.
Assert misuse:
- A contract uses
assert(condition)to validate user-supplied input. assertconsumes all remaining gas when it fails (pre-EIP-3855 behavior) and does not refund.- An attacker triggers the assert repeatedly, wasting enormous amounts of gas for legitimate users.
- Additionally, failed
assertstatements are caught differently in try/catch blocks thanrequirefailures.
Arithmetic overflow (missing check):
- A contract performs
total += amountwithout SafeMath or Solidity 0.8.x overflow protection. - An attacker passes a large
amountthat causestotalto wrap around to a small value. - The contract believes the total is small when it is actually astronomically large.
- Arbitrary amounts are credited or debited due to the wrapped value.
Exploit Mechanics
The generator classifies the violation type from the finding description:
| Description contains | Violation type | Severity |
|---|---|---|
comparison, equal, boundary | incorrect_comparison | Medium: off-by-one, draining |
require, check, validation, zero | missing_validation | High: division by zero, invalid state |
assert, invariant | assert_misuse | Low: gas waste, incorrect failure mode |
overflow, underflow, arithmetic | arithmetic_check_missing | Critical: value manipulation |
Evidence collected: violation type, finding location, severity classification. Estimated gas: 50,000.
// VULNERABLE: Incorrect comparison allows draining reserves
contract VulnerableVault {
uint256 public balance;
uint256 public reserve = 1000; // Protected minimum
function withdraw(uint256 amount) external {
require(amount <= balance); // Should be: amount <= balance - reserve
balance -= amount;
_transfer(msg.sender, amount);
}
}
// VULNERABLE: Missing zero check
contract VulnerableDistributor {
function distribute(uint256 total, uint256 shares) external {
// shares could be 0 — division by zero!
uint256 perShare = total / shares;
_distribute(perShare);
}
}
// VULNERABLE: Assert used for input validation
contract VulnerableToken {
function transfer(address to, uint256 amount) external {
assert(amount <= balances[msg.sender]); // Should be require()!
// If assert fails: wastes all gas, no refund
balances[msg.sender] -= amount;
balances[to] += amount;
}
}
// VULNERABLE: No overflow protection (Solidity < 0.8.0)
contract VulnerableAccounting {
uint256 public totalDeposits;
function deposit(uint256 amount) external {
totalDeposits += amount; // Can overflow in Solidity 0.7.x and below
balances[msg.sender] += amount;
}
}
// SECURE: All four violations corrected
contract SafeVault {
uint256 public balance;
uint256 public constant RESERVE = 1000;
// Fix 1: Correct comparison boundary
function withdraw(uint256 amount) external {
require(amount > 0, "Amount must be positive");
require(balance >= RESERVE + amount, "Insufficient balance above reserve");
balance -= amount;
_transfer(msg.sender, amount);
}
// Fix 2: Zero check before division
function distribute(uint256 total, uint256 shares) external {
require(shares > 0, "Shares must be positive");
uint256 perShare = total / shares;
_distribute(perShare);
}
// Fix 3: require() for user input, assert() for invariants only
function transfer(address to, uint256 amount) external {
require(amount <= balances[msg.sender], "Insufficient balance"); // User error
balances[msg.sender] -= amount;
balances[to] += amount;
assert(balances[msg.sender] + balances[to] <= totalSupply); // True invariant
}
// Fix 4: Solidity 0.8.0+ built-in overflow protection (or SafeMath)
// Solidity 0.8.0 throws on overflow automatically
function deposit(uint256 amount) external {
totalDeposits += amount; // Safe in 0.8.0+
balances[msg.sender] += amount;
}
}
Remediation
- Detector: Requirement Violations Detector
- Remediation Guide: Requirement Violations Remediation
Each violation type requires a targeted fix:
Incorrect comparisons: Audit every comparison operator near balance, allowance, or limit checks. Use formal verification or fuzz testing to test boundary values (0, 1, max-1, max).
Missing validations: Add guard clauses at function entry for all user-controlled inputs:
require(amount > 0, "Amount must be positive");
require(denominator != 0, "Division by zero");
require(recipient != address(0), "Cannot send to zero address");
Assert misuse: Reserve assert() for mathematical invariants that should never be false given correct code. Use require() for all user input validation and business logic checks. If an assert can be triggered by user input, it is a bug.
Arithmetic overflows: Upgrade to Solidity 0.8.0+ for automatic overflow protection. For contracts that must use 0.7.x or below, apply OpenZeppelin’s SafeMath for all arithmetic on user-controlled values.