Rounding Direction
The deliberate choice, made per operation, of whether integer division rounds up or down so that every truncation favours the protocol rather than the caller.
Rounding direction is a security boundary, not a numerical detail.
The EVM has no fractions. Every division truncates, and every truncation moves value by one wei. In a protocol where the same operation runs millions of times and can be invoked adversarially, the question of who receives that wei is a design decision that has to be made deliberately at every division — and made the same way each time.
The rule
The direction is chosen so the truncation always favours the pool over the caller. Concretely:
- An amount the caller owes the protocol rounds up.
- An amount the protocol pays the caller rounds down.
Uniswap V3 implements this by carrying an explicit roundUp parameter through SqrtPriceMath and FullMath, rather than letting the direction fall out of whatever the expression happens to do. mulDivRoundingUp exists as a separate function precisely so that the choice is visible at every call site.
The pool's invariant is that its balance after an operation is at least what the math says it should be. Rounding in the caller's favour anywhere breaks that by one wei, and one wei that can be extracted repeatedly is not one wei.
Why the direction flips with the operation, not the token
The same quantity rounds differently depending on which side of the trade it is on. In a swap, the input amount rounds up and the output amount rounds down — both favour the pool, and they round in opposite directions. In a mint, the amounts the LP must deposit round up. In a burn, the amounts returned round down.
This is why "round up for safety" is not a rule that survives contact with the code. There is no globally safe direction. There is only the direction that favours the pool for this operation, which requires knowing which way value is flowing.
The cost of getting it wrong
Rounding bugs are among the most expensive class of DeFi failure because they are quiet. Nothing reverts, no invariant check fires, and the discrepancy is invisible in any single transaction. It surfaces only as a slow drain, or as a sudden one when someone notices the loop can be run cheaply.
A protocol whose math is almost right in this way has failed in the same manner as one whose math is badly wrong, just more slowly. Reviewing a concentrated-liquidity fork means checking the direction at every division against the flow of value, not checking that the formula matches the whitepaper.
What to look for
Three patterns account for most of the findings. A roundUp argument passed as a literal false where the value flows toward the pool. A refactor that replaces mulDivRoundingUp with mulDiv because the two "do the same thing." And a fork that adds a new fee or discount without asking which direction its truncation should go, defaulting to the compiler's floor and quietly handing the difference to the caller.
Related Terms
Rounding Error
Precision loss in mathematical calculations that can be exploited through repeated operations to drain protocol funds.
Concentrated Liquidity
A liquidity provision model where LPs can specify custom price ranges for their capital.
sqrtPriceX96
Fixed-point number format used in Uniswap v3 representing the square root of price multiplied by 2^96.
Audit Severity Matrix
The two-axis framework auditors use to assign Critical, High, Medium, Low, or Informational severity to findings based on impact times likelihood.
Need expert guidance on Rounding Direction?
Our team at Zealynx has deep expertise in blockchain security and DeFi protocols. Whether you need an audit or consultation, we're here to help.
Get a Quote