The Even Number DoS: Cooking a Blockchain with Bad Math
Jan 4, 2026·7 min read
Executive Summary (TL;DR)
A math function in Frontier's Ethereum layer is secretly 20x slower for even numbers than odd ones, but the gas fee was the same. Attackers could spam cheap transactions using even numbers to trigger this slow path, causing a Denial of Service and potentially halting the blockchain.
CVE-2023-28431 is a critical Denial of Service vulnerability in Frontier, an Ethereum compatibility layer for Substrate. The issue stems from a gross miscalculation in transaction costs for a cryptographic precompile. A specific mathematical operation, modular exponentiation, is dramatically slower when using even numbers as a modulus due to an underlying library's implementation. Frontier failed to charge extra for this slow path, allowing an attacker to submit cheap transactions that consume massive amounts of computational power, effectively grinding the entire network to a halt for pennies on the dollar.
Welcome to the Precompile Casino
In the world of blockchain, especially complex ecosystems like Substrate and its Ethereum compatibility layer, Frontier, performance is everything. To speed things up, networks use 'precompiles'—highly optimized, native code functions for common but computationally brutal operations like cryptography. Think of them as the VIP fast lane for math that would otherwise clog up the network.
One of the most important precompiles is modexp, which calculates (base^exponent) % modulus. This isn't just for fancy algebra; it's the bedrock of countless cryptographic schemes, including RSA and certain zero-knowledge proofs. Because it's so critical and so expensive to run, its gas cost must be meticulously calculated. Get it wrong, and you've just handed attackers a key to the kingdom's engine room.
Frontier, trying to be a faithful Ethereum clone, implemented this precompile. It outsourced the heavy lifting for big number math to a popular Rust library, num-bigint. This is standard practice. You don't roll your own crypto or big number math unless you have a death wish. Unfortunately, this reliance on a third-party library, combined with a flawed understanding of its performance characteristics, created a perfect storm.
An Odd Sense of Speed
The root of this vulnerability is a classic case of 'not all inputs are created equal'. The num-bigint library's modular exponentiation function has a secret performance quirk: it's blazingly fast for odd moduli but crawls at a snail's pace for even ones.
Why the discrepancy? For odd moduli, the library can use a highly optimized algorithm called Montgomery reduction, which is a clever way to perform modular arithmetic without costly division operations. It’s the mathematical equivalent of a finely tuned F1 car. But for even moduli, this algorithm doesn't work. The library has to fall back to a much slower, more generic method—a 'plain power' algorithm. This is the equivalent of taking that F1 car off-road; it's going to be a slow, painful ride.
Here lies the fatal flaw: Frontier's gas calculation for the modexp precompile was completely oblivious to this fact. It charged the same toll whether you were driving the F1 car on a racetrack or through a swamp. An attacker could force the network to take the slow, swampy route over and over again while paying the low, racetrack price. This economic imbalance is the heart of the Denial of Service vulnerability.
The Smoking Gun in Rust
Let's look at the code. Before the fix, the calculate_gas_cost function was blissfully unaware of the modulus's parity. It took in lengths and the exponent, did some math, and spat out a number. It had no idea that certain inputs would send the CPU on a long, arduous journey.
Then comes the patch. It’s both beautifully simple and a damning admission of the oversight. The fix introduces a single, crucial change. First, the function signature is altered to accept a new boolean parameter: mod_is_even.
-fn calculate_gas_cost(
- base_length: u64,
- mod_length: u64,
- exponent: &BigUint,
- exponent_bytes: &[u8],
-) -> u64 {
+fn calculate_gas_cost(
+ base_length: u64,
+ mod_length: u64,
+ exponent: &BigUint,
+ exponent_bytes: &[u8],
+ mod_is_even: bool,
+) -> u64 {And at the end of the calculation, a new line acts as a punitive tax on inefficiency. If the modulus is even, the gas cost is multiplied by 20. A simple if statement turns an economically viable attack into financial suicide.
MIN_GAS_COST,
multiplication_complexity * iteration_count / 3,
)
+ .saturating_mul(if mod_is_even { 20 } else { 1 })
}This is a classic 'stop the bleeding' fix. It doesn't fix the underlying slow algorithm in num-bigint, nor does it swap it for a better one. It just makes the slow path so expensive that nobody in their right mind would ever want to use it. Problem deferred, disaster averted.
Cooking the Books... and the CPU
So, how does an attacker weaponize this? It's disturbingly simple. The goal isn't to compute a result, but to maximize the ratio of CPU time / gas cost. This is the holy grail of algorithmic complexity attacks on blockchains.
First, the attacker crafts a transaction, or a series of them, that calls the modexp precompile. The parameters are chosen carefully:
baseandexponent: These are set to large values to ensure the calculation is non-trivial.modulus: This is the key. The attacker chooses a large, even number.
The attacker then submits this transaction to the network. The gas estimator looks at the transaction, sees a modexp call, and applies the flawed, uniform gas formula. It quotes a price that seems reasonable. The attacker accepts and pays the fee.
When a validator node picks up this transaction, it begins execution. It hits the modexp precompile, passes the parameters to the num-bigint library, and suddenly finds itself on the slow path. The CPU usage spikes as it grinds through the inefficient plain power algorithm. A single block that should have taken milliseconds to process might now take seconds, or even longer if filled with these poison transactions.
By spamming the network with these cheap-but-costly transactions, the attacker can overwhelm every validator. Block times skyrocket, transaction finality grinds to a halt, and the chain becomes effectively unusable. This is a denial of service in its purest form, achieved not by flooding the network with traffic, but by tricking it into doing hard math for cheap.
The Impact: Denial of Service, Denial of Sanity
The impact of a successful exploit goes far beyond a temporary slowdown. In a decentralized system built on consensus, validator performance is a cornerstone of security. When validators start lagging, they risk falling out of sync with the rest of the network.
If a significant portion of validators are bogged down processing these malicious modexp calls, they might fail to produce or validate new blocks within the allotted time. This can lead to an increase in 'uncle' blocks, reduced network throughput, and in a worst-case scenario, a complete chain halt if consensus cannot be reached.
This isn't just a technical problem; it's an economic one. It shatters the illusion that gas fees accurately represent computational cost. Users and developers build applications with the assumption that the gas model prevents abuse. A vulnerability like this proves that those assumptions can be dangerously wrong. It allows an attacker to monopolize the network's most valuable resource—compute time—at a steep discount, undermining the entire system's stability and trustworthiness.
The Fix: A 20x 'Even Number' Tax
The remediation for CVE-2023-28431 is a textbook example of a tactical, pragmatic fix. Instead of diving into the num-bigint library to optimize its math (a complex and time-consuming task) or replacing it entirely, the Frontier developers opted for an economic solution: they slapped a hefty tax on the vulnerability.
By multiplying the gas cost by 20 for any modexp call with an even modulus, they instantly flipped the attacker's cost-benefit analysis. What was once a cheap way to bog down the network is now prohibitively expensive. The attack is no longer economically viable. This is a common pattern in blockchain security: when you can't fix the code, fix the price.
However, this isn't a permanent solution. The advisory itself notes that a long-term fix would involve addressing the performance issue within num-bigint or switching to a different library altogether. The 20x multiplier is essentially a magic number—an educated guess at a value high enough to deter attacks. A determined attacker might still find edge cases where the cost is worth it, and legitimate applications that need to use even moduli (however rare) are now unfairly penalized. It's a patch, not a cure.
Fix Analysis (1)
Technical Appendix
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HAffected Systems
Affected Versions Detail
| Product | Affected Versions | Fixed Version |
|---|---|---|
Frontier paritytech | All versions before the inclusion of commit 5af12e94d7dfc8a0208a290643a800f55de7b219 | Not specified, but patched in commit 5af12e94d7dfc8a0208a290643a800f55de7b219 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-682: Incorrect Calculation |
| Attack Vector | Network |
| Attack Complexity | Low |
| Privileges Required | None |
| CVSS v3.1 Score | 7.5 (High) |
| EPSS Score | 0.25% (0.00249) |
| Impact | Denial of Service |
| Exploit Status | Proof-of-Concept |
MITRE ATT&CK Mapping
MITRE ATT&CK Mapping
The software performs a calculation that results in an incorrect value. In this case, the gas cost calculation did not accurately reflect the computational resources required for modular exponentiation operations with even moduli, creating an economic imbalance that leads to a Denial of Service condition.
Vulnerability Timeline
Vulnerability Timeline
Subscribe to updates
Get the latest CVE analysis reports delivered to your inbox.