← Back to blog
Tadeo - SecLat SecuritySeptember 4, 2026

Notional Finance V1: how a uint128 conversion could have hidden 2^128 of debt

A technical analysis of the reported Notional Finance V1 incident, in which an unsafe conversion could have valued an extreme debt at zero and enabled the withdrawal of roughly $1.73 million.

Notional Finance V1: how a uint128 conversion could have hidden 2^128 of debt

Reading time: 8 minutes

On September 3, 2026, approximately $1.73 million in DAI and USDC left the Notional Finance V1 Escrow contract. CryptoTimes reported that amount and described the subsequent movement of the funds. The withdrawal transaction is public on Ethereum, but by itself it does not prove the full preceding sequence or the intent of the party that executed it.

The technical hypothesis published by EtherWorld, which can be compared with inspection of the public code and referenced transactions, points to a direct conversion of a large integer to uint128 in a critical solvency-calculation path. By constructing a debt of exactly 2^128, the attacker could have caused the system to interpret it as zero.

The incident does not yet have an official, authoritative post-mortem from Notional Finance. Therefore, the loss, root cause, and sequence described in this article should be understood as third-party reporting and public evidence available at the time of writing, not as an independent reconstruction proving every step of the attack.

What is confirmed and what remains unresolved

The reported withdrawal transaction is listed as successful on Ethereum. CryptoTimes reported that the contract paid approximately:

  • 69,257.37 DAI
  • 1,658,524.86 USDC

CryptoTimes also reported that these assets were subsequently converted into approximately 689.2 ETH and sent to Tornado Cash. Those figures and that path are presented here as that outlet's reporting, although public transactions allow specific movements to be examined.

However, authoritative information is still missing on:

  • The final loss acknowledged by Notional Finance.
  • The impact on V1 users or historical positions.
  • Containment measures adopted by the team.
  • A root cause validated through an official post-mortem.
  • Any potential recovery of funds.

How the solvency check worked

Notional V1 represented fixed-term loans through positions called fCash. A positive position represented the right to receive funds at maturity. A negative position represented an obligation to pay.

Notional's documentation describes free collateral as the value available after accounting for assets, debt, discounts, and safety margins.

That calculation protected an essential property:

An insolvent account must not be able to create positions or withdraw real assets from the protocol.

The conversion that could have turned debt into zero

The public ExchangeRate.sol code contains this operation within _convertToETH():

uint128 absBalance = uint128(balance.abs());

balance.abs() produces an unsigned value of up to 256 bits. The code then converts it directly to uint128, a type that can represent only values from 0 to 2^128 - 1.

If the value exceeds that limit, an explicit conversion of this kind does not preserve the high-order bits. The result is equivalent to retaining only the lower 128 bits.

EtherWorld reconstructed a setup involving two obligations whose sum was exactly:

1 + (2^128 - 1) = 2^128

The reported preparation transaction can be inspected publicly. The interpretation that these operations formed part of the exploitation path remains EtherWorld's reconstruction, not an official Notional conclusion.

The lower 128 bits of 2^128 are all zero. As a result, when the value was reduced to uint128, the debt could have been represented as 0.

The critical operation could have been an unchecked narrowing conversion, also known as an unsafe narrowing cast or truncation.

The same file uses SafeCast.toUint128() for other conversions. That variant reverts when a value does not fit in 128 bits. Applying an equivalent check to the balance would have prevented 2^128 from proceeding as zero.

Why one conversion does not explain the entire incident

The truncation could have been exploitable through the interaction of several assumptions.

The public Portfolios.sol contract allowed fCash pairs to be created through mintfCashPair(). The function recorded an obligation for the payer and a positive position for the receiver.

It then checked the payer's free collateral:

(int256 fc, , ) = freeCollateral(payer);
require(fc >= 0, "insufficient free collateral");

The receiver did not undergo the same check because the design assumed that receiving a positive position always improved its solvency.

EtherWorld's reconstruction, together with inspection of the linked public contracts and transactions, suggests that the attack could have combined:

  1. The ability to create fCash pairs with controlled values.
  2. A debt constructed exactly at the 2^128 boundary.
  3. A conversion to uint128 that could have truncated that debt to zero.
  4. A solvency check applied only to the payer.
  5. Settlement of fabricated positions to convert them into withdrawable DAI and USDC balances.

The consistency of these elements with the public code does not replace an official attribution of causality. Under that hypothesis, the economic system would have relied on a value that had already lost information during conversion.

What DeFi protocols should audit

This case provides concrete controls for any protocol that calculates debt, collateral, or withdrawal capacity.

1. Reject unchecked narrowing conversions

Every conversion from a wider type to a smaller one should revert if the value is out of range.

uint128 absBalance = SafeCast.toUint128(balance.abs());

Reviewing additions and multiplications alone is not enough. Explicit casts are also part of the arithmetic attack surface.

2. Test mathematical boundaries

Tests should include at least:

  • 0
  • 1
  • 2^128 - 1
  • 2^128
  • 2^128 + 1
  • Equivalent negative values when signed integers are used

3. Express solvency invariants

A test should verify properties such as:

  • Creating offsetting positions cannot generate net withdrawable value.
  • A larger debt must never produce a lower valuation through truncation.
  • An account with negative free collateral cannot withdraw funds.
  • The total issued claims cannot exceed the assets backing the system.

4. Review both sides of an operation

When a function simultaneously creates an obligation and a claim, the audit must analyze the payer, the receiver, and the overall relationship between them. An assumption valid for ordinary transfers can fail when an attacker controls every participating account.

5. Do not ignore legacy contracts

The incident affected Notional V1 code, a legacy version. Older software remains part of the attack surface while it retains funds, permissions, liquidity, or executable paths.

The central lesson

In DeFi systems, a solvency check is only as reliable as every conversion that feeds its result.

A sound review is not limited to searching for reentrancy, manipulable oracles, or access-control issues. It also requires asking whether every value retains its economic meaning when its type, precision, or sign changes.

This article will be updated when Notional Finance publishes an authoritative technical post-mortem with the root cause and final impact.

Sources

  1. Notional Finance V1, ExchangeRate.sol code
  2. Notional Finance V1, Portfolios.sol code
  3. Notional Finance, free collateral documentation
  4. Etherscan, reported withdrawal transaction
  5. Etherscan, reported preparation transaction
  6. CryptoTimes, Notional Finance Escrow Contract Faces Reported $1.7M Exploit
  7. EtherWorld, Notional Finance Exploit Drains $1.7M
SECLAT - Security & Audit

SECLAT - Expertos en seguridad blockchain y auditorías de contratos inteligentes.

Estadísticas Clave

200+
Contratos Auditados
0
Incidentes Críticos
20+
Clientes Satisfechos
$100M+
Protegidos

Contactanos

Si buscas una auditoría de seguridad o una consulta, Contactanos.

© 2026 SECLAT Security. Todos los derechos reservados.