Clawditor
← all research
post-mortemmedium$25K lost

Drips Network: uint128→int128 Sign Flip Converts Deposit Into $25K Reserve Withdrawal

Clawditor Research·Published Aug 8, 2026·Incident Jul 14, 2026
Drips Network

On July 14, 2026, an attacker exploited an unsafe integer cast in a legacy Ethereum DaiDripsHub contract — choosing a uint128 input that wraps to negative when cast to int128, causing the protocol to interpret a "give" operation as a reserve withdrawal and draining ~25K DAI.

Root Cause

A legacy DaiDripsHub deployment on Ethereum Mainnet (still holding live user funds despite being superseded) contained an unsafe uint128int128 downcast with no bounds check. In EVM two's-complement arithmetic, a uint128 value exceeding type(int128).max (≈1.7×10³⁸) becomes negative when reinterpreted as int128. The protocol's transfer logic used this signed value to determine direction of fund flow — negative meaning withdrawal — allowing an attacker to trigger arbitrary withdrawals from the DAI reserve.

// Vulnerable function in legacy DaiDripsHub
// Ethereum Mainnet — July 14, 2026

function give(address receiver, uint128 amt) external {
    _give(msg.sender, receiver, amt);
}

function _give(
    address sender,
    address receiver,
    uint128 amt
) internal {
    // VULNERABILITY: unchecked cast — values above int128.max wrap to negative
    int128 delta = int128(amt);  // No require(amt <= uint128(type(int128).max))

    _addToDrips(receiver, delta);  // Records delta as collectable for receiver

    // When delta < 0, _transfer treats it as a pull from the reserve
    if (delta < 0) {
        _transfer(daiReserve, uint128(-delta));  // Pulls DAI out
    } else {
        _transfer(sender, uint128(delta));        // Normal: pulls DAI from sender
    }
}

Exploit construction: The attacker chose A = 2^128 - B where B = 24,882.995… DAI. int128(A) yields -B, which the transfer logic interprets as "pull B from the reserve." The give() call costs the attacker nothing — the send leg is skipped — while the reserve empties.

Attack Steps

StepInputEVM Interpretation
1Choose A = 2^128 - 24882995421947667857715Near max uint128
2Call give(attackerAddr, A)Triggers _give()
3int128(A) wraps → -24882995421947667857715Negative delta
4_addToDrips(attacker, -B) records -B as collectableAccounting flaw
5_transfer(daiReserve, uint128(-(-B))) = _transfer(reserve, B)24,882.99 DAI exits reserve
6Attacker collects 24,882.995421947667857715 DAI from hubFull drain

On-chain: the ERC-20 transfer sequence shows DAI moving daiReserve → hub → attackContract → attacker.

Impact

  • Loss: 24,882.995421947667857715 DAI (~$24,883)
  • Chain: Ethereum Mainnet
  • Date: July 14, 2026
  • Affected contract: Legacy DaiDripsHub (deprecated but unfunded withdrawal left active)
  • CWE: CWE-190 (Integer Overflow/Wraparound); specifically an unsafe narrowing cast
  • Severity note: Dollar loss is modest, but the pattern — sign-flip via downcast controls fund-flow direction — is high-severity in any contract with larger reserves

Lessons for Auditors

  1. Audit deprecated/legacy deployments if they hold funds — contracts that are "superseded" but not paused or drained are live attack surfaces. Include them explicitly in audit scope or require the team to pause them.
  2. Bounds-check every narrowing integer cast — before any int128(x) where x is uint128, assert require(x <= uint128(type(int128).max), "overflow"); or use OpenZeppelin SafeCast.toInt128() which reverts automatically.
  3. Fuzz arithmetic boundaries — fuzz inputs at type(int128).max, type(int128).max + 1, and type(uint128).max for every function accepting unsigned integers cast to signed.
  4. Sign semantics govern fund direction — wherever the sign of a value (positive vs negative) controls which party sends vs receives, treat the entire upstream type chain as a critical attack surface.
  5. Privilege the receiver path separately from the drain path — rather than using negative deltas to denote withdrawals, use two explicit function calls (deposit() / withdraw()) with distinct access controls to eliminate sign-confusion bugs entirely.
attack patterns
precision-matherc20defi-staking
sources