Skip to content
#20 largest Arithmetic 2021

The Uranium Finance hack — ~$50M lost

Loss~$50M
Date28 Apr 2021
ChainBNB Chain
Failure classArithmetic
In assets$31M later seized by US authorities
TargetAMM · one digit
1

What happened

A migration bumped the pair contract's precision constant from 1,000 to 10,000 — but the change did not reach the swap() function's constant-product sanity check, which still multiplied the reserves by 1000**2 while the balances on the other side of the comparison were scaled by 10,000. The invariant was 100× too loose. Anyone could swap in dust and take nearly the whole reserve. The project had even been told about a related issue in an audit, patched it, and the patch was not enough.

2

How the attack ran

  1. Swap in a tiny amountOf either side of the pair
  2. swap() checks the K invariantBalances are scaled by 10,000
  3. Reserves scaled by 1000²Left and right side disagree — the check is 100× too loose
  4. Take the reservesDust in, the pool out — ~$50M
3

The code

UraniumPair.sol — swap()
uint balance0Adjusted = balance0.mul(10000).sub(amount0In.mul(16));
uint balance1Adjusted = balance1.mul(10000).sub(amount1In.mul(16));

require(
    balance0Adjusted.mul(balance1Adjusted) >=
    uint(_reserve0).mul(_reserve1).mul(1000**2),      // ❌ should be 10000**2
    'UraniumSwap: K'
);

// left side scaled by 10000² = 100,000,000
// right side scaled by  1000² =   1,000,000
// → the K invariant is satisfied by 1/100th of the value it should require.

→ result: swap in dust, walk out with the pool
4

What would have caught it

What an audit looks for: magic numbers that appear in more than one place. A constant repeated across functions is a bug waiting for the next refactor — hoist it into a single named constant so the compiler makes the mistake impossible. And every core invariant deserves a property test that would fail loudly at 100× drift.
6

Sources

Every figure on this page comes from the post-mortems above, not from us. Losses are US dollars at the time of the incident.

Check your own contract for this

Arithmetic is one of the 203 classes the SaferICO scanner checks for. It will not review your signing process — but it will read your Solidity.

Run the scanner See how it is attacked Read the docs