📈 Get daily crypto insights that make you smarter about your money

Detecting Integer Rounding Vulnerabilities in Solidity: An Advanced Smart Contract Auditing Walkthrough

The $7.4 million exploit of Hundred Finance on April 15, 2023, exposed a class of vulnerability that continues to plague DeFi protocols: integer rounding errors in smart contract arithmetic. While the attack was sophisticated in its execution, the root cause was a fundamental property of the Ethereum Virtual Machine — the inability to handle fractional numbers. This advanced walkthrough dissects the vulnerability and provides a systematic methodology for detecting similar flaws in any Solidity codebase.

The Objective

This tutorial aims to equip experienced smart contract developers and auditors with the knowledge and tools to identify integer rounding vulnerabilities before they reach production. By the end of this walkthrough, you will understand how rounding errors compound in lending protocol exchange rate calculations, how to reproduce these attacks in a test environment, and how to implement defensive coding patterns that eliminate this class of vulnerability entirely.

The Hundred Finance exploit provides our case study. The protocol used Compound-derived code deployed on Optimism, where low-liquidity pools created the empty-market conditions that enabled the attack. The core issue: the EVM rounds down in all division operations, and under specific conditions, this rounding can be exploited to manipulate accounting invariants.

Prerequisites

This tutorial assumes proficiency with Solidity development, familiarity with the EVM’s integer arithmetic model, and experience with lending protocol architectures. You should be comfortable reading Compound-style code with cToken exchange rates and understand how collateralization calculations work in lending protocols.

You will need a local development environment with Foundry or Hardhat installed, access to an Optimism RPC endpoint for mainnet forking, and the Hundred Finance contract source code from their GitHub repository or Etherscan verified contracts.

Step-by-Step Walkthrough

Step 1: Understanding the Exchange Rate Model

Lending protocols like Compound and Hundred Finance use an exchange rate to convert between underlying tokens and their wrapped representations — in this case, WBTC and hWBTC. The exchange rate is calculated as total underlying supply divided by total hToken supply. When a pool is empty and has zero hToken supply, this calculation produces undefined behavior that must be explicitly handled.

In Solidity 0.5.16, which Hundred Finance used, all arithmetic is performed with uint256 integers. Division rounds toward zero. When the attacker deposited into an empty pool, the exchange rate calculation produced a value that could be manipulated through strategic deposits and withdrawals.

Step 2: Reproducing the Empty Pool Attack

To reproduce the vulnerability, fork the Optimism mainnet at a block before the exploit. Deploy a test contract that simulates the attacker’s strategy. First, initiate a flash loan of 500 WBTC from Aave. Deposit into the empty hWBTC pool to become the sole liquidity provider. Withdraw almost all deposits, leaving just 2 wei of hWBTC supply.

At this point, the critical rounding occurs. When the attacker redeems WBTC, the calculation involves dividing the underlying amount by the exchange rate. Due to rounding down, redeeming 500 WBTC — worth approximately $15 million at Bitcoin’s price of $30,315 — requires only 1 wei of hWBTC instead of the mathematically correct amount. The attacker gains an enormous collateral position for virtually no cost.

Step 3: Identifying Vulnerable Code Patterns

The vulnerable pattern manifests in the redeemUnderlying function. Look for division operations where the divisor can approach zero or where the result of a multiplication before division can create exploitable rounding. Specifically, audit any code path where:

The total supply of wrapped tokens can reach near-zero values. The exchange rate is calculated as a ratio of total assets to total supply. Division precedes multiplication in any token conversion. The contract allows deposits and withdrawals in the same transaction without time locks.

In the Hundred Finance case, the redeemUnderlying function calculated the hToken amount needed using the formula: hTokenAmount = underlyingAmount * 10^18 / exchangeRate. When the exchange rate was artificially inflated by the attacker’s manipulation, this division rounded down to 1 wei.

Step 4: Implementing Defensive Patterns

The primary defense against integer rounding attacks in lending protocols is to enforce minimum liquidity thresholds. Implement a minimum deposit that creates a permanent, non-withdrawable liquidity position when a market is initialized — similar to how Uniswap V2 permanently locks the first LP tokens.

Additionally, use SafeMath libraries that detect and revert on unexpected rounding, implement exchange rate bounds that reject calculations outside expected ranges, and add reentrancy guards on all functions that modify pool state. Consider upgrading to Solidity 0.8.x, which includes built-in overflow and underflow checks.

For exchange rate calculations specifically, always perform multiplication before division to minimize precision loss. When the order of operations matters for precision, explicitly document the reasoning and test with edge cases including zero-supply and minimum-supply scenarios.

Troubleshooting

If you encounter issues reproducing the attack in a local fork, verify that you are using the correct block number and that the Hundred Finance contracts have the exact same state as they did before the exploit. The attack depends on the pool being empty, so ensure no other deposits exist in your forked environment.

When testing defensive patterns, ensure your minimum liquidity threshold is large enough to prevent manipulation but small enough not to create an unreasonable barrier to market creation. A common approach is to lock the equivalent of $100 to $1,000 worth of the underlying asset, depending on the protocol’s intended scale.

If your Foundry tests show unexpected gas costs or transaction failures during exchange rate calculations, check for integer overflow in the intermediate multiplication steps. The Compound codebase uses a specific decimal precision that must be maintained throughout the calculation chain.

Mastering the Skill

Integer rounding vulnerabilities represent a broader class of precision loss issues in smart contract development. To master this area, study the full history of DeFi exploits involving mathematical errors, including the bZx flash loan attacks, the Cover Protocol exploit, and the Cream Finance incidents. Each of these cases demonstrates a different manifestation of the same fundamental challenge: representing real-world financial calculations with integer arithmetic.

Build a personal library of test cases for lending protocol edge states — empty pools, single depositor pools, maximum utilization, and flash loan scenarios. Integrate these tests into your CI pipeline for any DeFi project. Consider contributing to open-source audit tools like Slither or Mythril by adding detectors specifically designed for rounding error patterns in exchange rate calculations.

The field of formal verification offers the most rigorous approach to eliminating these vulnerabilities. Tools like Certora Prover and Halmos can mathematically prove that exchange rate calculations maintain their invariants under all possible inputs, including adversarial manipulation attempts. Investing time in learning these tools will distinguish you as a security auditor capable of preventing the next generation of DeFi exploits.

Disclaimer: This article is for educational purposes only. Always conduct professional security audits before deploying smart contracts to production. The techniques described should be used for defensive purposes only.

🌱 FOR BUSINESSES BitcoinsNews.com
Reach 100K+ Crypto Readers
Sponsored content, press releases, banner ads, and newsletter placements. Put your brand in front of Bitcoin's most engaged audience.

8 thoughts on “Detecting Integer Rounding Vulnerabilities in Solidity: An Advanced Smart Contract Auditing Walkthrough”

  1. the EVM cant do fractions. thats the whole problem. every Solidity dev learns this the hard way, usually after losing testnet ETH to a rounding bug

    1. the EVM fraction problem is solvable with fixed point libraries. the issue is developers not using them because Solidity doesnt warn you about implicit precision loss

      1. solidity 0.8 helped with overflow checks but did nothing for precision loss. devs still need to manually use mulDiv and round toward zero. the language should enforce this

  2. the empty market attack vector on compound forks is well documented at this point. theres no excuse for not guarding against it in 2023

  3. good technical breakdown. the exchange rate manipulation through low-precision arithmetic is subtle. most auditors would miss it on a quick scan

    1. most auditors would miss it because the exploit requires an empty market precondition. you cant easily test for that in a standard audit unless you specifically model the attack

  4. $7.4M on Optimism where gas is cheap enough to spam transactions until the rounding error compounds. L2s have their own unique attack surfaces people overlook

    1. exactly. people assume L2s are safer but lower gas costs mean attackers can run exploit transactions repeatedly for pennies. the economics of attacks change on L2

Leave a Comment

Your email address will not be published. Required fields are marked *

BTC$67,137.00+4.7%ETH$1,839.35+10.4%SOL$75.65+11.8%BNB$627.90+3.3%XRP$1.29+13.0%ADA$0.1888+12.9%DOGE$0.0904+4.5%DOT$1.04+8.6%AVAX$7.05+7.8%LINK$8.54+8.7%UNI$2.74+9.7%ATOM$2.00+1.3%LTC$46.13+4.4%ARB$0.0895+9.0%NEAR$2.49+19.5%FIL$0.8124+6.7%SUI$0.8236+9.7%BTC$67,137.00+4.7%ETH$1,839.35+10.4%SOL$75.65+11.8%BNB$627.90+3.3%XRP$1.29+13.0%ADA$0.1888+12.9%DOGE$0.0904+4.5%DOT$1.04+8.6%AVAX$7.05+7.8%LINK$8.54+8.7%UNI$2.74+9.7%ATOM$2.00+1.3%LTC$46.13+4.4%ARB$0.0895+9.0%NEAR$2.49+19.5%FIL$0.8124+6.7%SUI$0.8236+9.7%
Scroll to Top