October 20, 2026
|
Exploit Postmortem
Cover image for "Arrakis Finance's $7.2K Loss and How Olympix Would Have Prevented It"

Arrakis Finance's $7.2K Loss and How Olympix Would Have Prevented It

Date: August 23, 2026

Chain: Ethereum

Loss: 2.94 WETH, about $7.2K

Class: vault mint and burn priced from live pool state with no same-transaction protection

On August 23, 2026, an attacker borrowed 1,800 WETH from Morpho Blue, put it to work against an old Arrakis vault holding ENS and WETH, and repaid the loan in the same transaction, leaving the vault 2.94 WETH short. The vault was a legacy G-UNI contract from the first generation of Arrakis, and nobody could pause it, because the team had renounced every privileged role on those contracts two months earlier.

The loss was small, about $7,200, but the mechanism is one every vault builder should know. The vault priced both deposits and withdrawals from the Uniswap V3 pool's live state at the instant of the call, so an attacker who could change that state between minting shares and burning them could collect more on the way out than they put in.

A Wrapper Around a Uniswap V3 Position

Uniswap V3 lets liquidity providers concentrate their capital in a chosen price range, which earns more fees but means someone has to pick the range and manage it. G-UNI vaults handled that for depositors by pooling everyone's capital into one shared Uniswap V3 position and issuing ERC-20 shares against it. Anyone could mint shares by depositing the two tokens, and anyone could burn shares to take back a proportional slice of the underlying tokens plus the fees the position had earned.

Both operations depended on one internal calculation, getUnderlyingBalances(), which works out how much of each token the vault's position holds right now. According to the crypto.training reproduction of the exploit, that function reads the pool's slot0, Uniswap V3's record of the current price and tick, which updates on every swap and isn't averaged over any period of time.

Two Prices in One Transaction

A vault share is a claim on a fraction of the position, and the size of that fraction in tokens depends on what getUnderlyingBalances() says at the moment of mint or burn. When the pool's price moves, the mix of the two tokens inside a concentrated position changes too, and so does the amount of fees waiting to be collected. If nothing ties a burn to the state the vault was in when the same shares were minted, a holder who can move the price in between gets paid out against a different picture of the vault than the one they paid into.

The teaching moment is that a vault's books have to stay fair across a round trip. Minting and then burning the same shares in one transaction should never return more than the deposit, and any pricing input that the depositor can move inside that round trip, like a spot price, breaks that guarantee. It works like a currency exchange booth that reads its rate off a screen the customer can reach, where buying, nudging the screen and selling back in the same visit pays every time.

The contract did carry a time-weighted price check with a deviation limit, but it wrapped only the manager's rebalance() path. The DeFiHackLabs reproduction, which was checked against the on-chain trace and the verified ArrakisVaultV1 source, found no time-weighted price and no deviation check on mint() or burn(), the two functions any depositor could call. SlowMist's alert describes the same gap from the other side, as the absence of any same-transaction mint and burn protection or state snapshot in the vault's burn accounting.

The Sandwich, Step by Step

The attack ran atomically, which means every step happened inside one transaction and would have reverted together if any step failed. The attacker's wallet, 0xa3B0...EB44, called an attack contract that borrowed 1,800 WETH from Morpho Blue, and the DeFiHackLabs reconstruction of that transaction lays out what came next, with the pool's token0 as WETH and token1 as ENS.

First, the attack contract swapped about 145.42 WETH into the ENS/WETH Uniswap V3 pool, pushing the price down to its limit and taking out about 13,292.5 ENS. With the pool's spot price skewed, it called mint() on the vault and deposited about 1,253.39 WETH and 13,159.59 ENS for 4,486.6 G-UNI shares, priced at the skewed spot. It then swapped about 132.93 ENS back into the pool, moving the price partway back, and called burn() on the same shares. The vault paid out about 1,248.41 WETH and 13,283.30 ENS, a mix with less WETH but more ENS than the deposit. The attacker swapped all of its ENS back to WETH and repaid the flash loan.

SlowMist's alert summarizes the same transaction as an atomic liquidity sandwich, with the burn paying out pending fees and liquidity pro rata against a position state that had changed since the shares were minted. What was left over after repayment was 2.941350352900037140 WETH taken from the vault at 0x7c68...bdde. The proof of concept notes that the attack contract sent a fixed 0.05 ETH tip to a separate address and forwarded the rest to the attacker's wallet, in transaction 0x6ae3...c672 in block 25817966.

A Contract That Couldn't Be Patched

Arrakis had already stepped away from this code. In a deprecation notice dated June 15, 2026, the team said it had set every privileged role on its V1 (formerly G-UNI) and V2 contracts to the zero address, including upgrade authority and manager rights, shut down its hosted interfaces, and advised users to withdraw, while the contracts kept running on-chain as deployed. After the exploit, Arrakis posted on X that the drained vault was a legacy G-UNI vault from 2021, that no Arrakis Pro vaults were affected and that its current architecture doesn't value deposits or withdrawals off the instantaneous spot price.

Immutability is often a selling point, since no one can change the rules on depositors. It also meant there was no key to pause the vault and no upgrade path to add a guard once the gap was public, so the code that ran on August 23 was the code as deployed.

How Olympix Follows a Share From Mint to Burn

Olympix reads a contract the way an attacker does, as states, transitions and entry points, and takes in its surrounding context, like the design of the Uniswap V3 position it wraps, to infer invariants the system depends on but never writes down. For a G-UNI vault, the invariant in one sentence is that minting shares and burning them in the same transaction must never return more than was deposited.

The engine maps every path through mint and burn and uses signals to decide which ones to attack. The signal here is share accounting that reads manipulable spot state, in this case slot0 through getUnderlyingBalances(), on both the deposit and redemption paths with no snapshot or same-transaction guard between them. Olympix's static analysis surfaces that pattern, and Olympix has flagged this class before in other codebases, where share and preview math read from spot state an attacker could move.

For this vault, BugPoCer's job is to break the round-trip rule. Its method, Counterexample-Guided Invariant Refutation, starts from what the system as a whole promises depositors and works outward toward the call sequences that could violate it, so it treats a mint and a burn of the same shares as one unit and searches for anything an outside caller can do around that pair of calls that changes what the burn pays. A swap against the pool is the obvious candidate, and a swap before the mint plus a partial swap back before the burn is enough to leave the round trip richer than it started. BugPoCer returns that as a counterexample, the concrete sequence of swap, mint, swap and burn, with the minimal conditions that trigger it and a generated Forge test that replays it, which is the August 23 sandwich produced in development instead of on mainnet.

This check runs automatically during development, at every merge and before release. That's where a gap between a guarded rebalance path and an unguarded mint and burn path shows up, since each path can look reasonable when reviewed on its own.

Guard Every Path That Prices a Share

The G-UNI vault's price guard sat on the rebalance path, and the mint and burn paths that depositors actually used had none. Builders wrapping concentrated liquidity can close this gap with a time-weighted price check, a snapshot taken at mint and honored at burn, or a lock that stops one address from minting and burning in the same transaction, and the useful test is whether every path that prices a share is covered. To see the counterexamples Olympix generates for your own vaults, book a technical walkthrough.

On-Chain References

Protocol: Arrakis Finance (Arrakis V1 / G-UNI ENS-WETH vault)

Chain: Ethereum

Date: August 23, 2026, 12:50:11 UTC

Loss: 2.941350352900037140 WETH

Attacker EOA: 0xa3B0...EB44

Attack contract: 0x028d...Af4a

Vulnerable vault (proxy): 0x7c68...bDDe

Vault implementation (ArrakisVaultV1): 0xd68b...6395

Flash loan: 1,800 WETH from Morpho Blue

Exploit tx: 0x6ae3...c672

Block: 25817966

Sources

SlowMist: Arrakis Finance exploit alert

DeFiHackLabs: ArrakisGUNI Uniswap V3 spot-price manipulation of vault mint/burn PoC

Arrakis Finance: V1 and V2 deprecation

Arrakis Finance: Response to the G-UNI vault incident

crypto.training: Reproduced Exploits, Arrakis G-UNI

More from Olympix:

No items found.

Ready to Shift Security Assurance In-House? Talk to Our Security Experts Today.