Calculated from recorded token losses using historical USD prices at the incident time.
0x025cf2858723369d606ee3abbc4ec01eab064a97cc9ec578bf91c6908679be750x61a7b3dae70d943c6f2ea9ba4ffd2fecc6af15e4ArbitrumOn Arbitrum block 166873292, transaction 0x025cf2858723369d606ee3abbc4ec01eab064a97cc9ec578bf91c6908679be75 exploited Hypervisor 0x61a7b3dae70d943c6f2ea9ba4ffd2fecc6af15e4 through its public deposit path and realized 211.903499271683579677 ETH of net profit. The attacker used only public venues: Balancer flash liquidity, a Uniswap V3 flash pool, the public UniProxy/Clearing deposit route, Algebra swaps, and a final WETH/USDC swap.
The root cause was valuation by a same-transaction manipulable spot price. Hypervisor deposit() read the current Algebra globalState() price, used it to value the incoming deposit, and used the same spot again to value the vault's existing inventory before scaling by total supply. That let a public depositor over-mint shares during a manipulated spot window and then redeem against a restored price basis.
Hypervisor is a vault over an Algebra pool position. Public deposits do not call Hypervisor directly; they flow through UniProxy deposit(), which first asks Clearing clearDeposit() whether the deposit is allowed and then forwards the mint to Hypervisor. In the incident state, Hypervisor whitelisted UniProxy, and UniProxy pointed to Clearing:
// Hypervisor
require(msg.sender == whitelistedAddress, "WHE");
// UniProxy
require(clearance.clearDeposit(deposit0, deposit1, msg.sender, to, pos, minIn), "deposit not cleared");
shares = IHypervisor(pos).deposit(deposit0, deposit1, to, msg.sender, minIn);
Source origin: verified Hypervisor and UniProxy contracts collected for the incident addresses.
Clearing was not an ownership gate here. The recorded configuration at block 166873292 shows depositOverride=true, twapOverride=true, priceThreshold=200, deposit0Max=300000000000, and deposit1Max=300000000000, while both the attacker EOA and the attacker helper contract were unlisted. That means the exploit path stayed public and had to fit only the public ratio and price checks.
The vulnerability class is an on-chain pricing attack against vault share issuance. Hypervisor deposit() converts token0 into token1 terms using the current Algebra spot and then computes minted shares from that instantaneous price. If total supply already exists, the function again uses the same spot to value the vault's token0 inventory before dividing by total supply. This creates a direct dependency between minted shares and a spot price that a trader can move within the same transaction. Clearing's TWAP and deposit-bound checks restrict the magnitude of a deposit but do not remove same-transaction manipulability, especially when the attacker can oscillate the spot and deposit repeatedly. As a result, the attacker can mint more shares than a fair pro-rata contribution deserves, withdraw after restoring the price direction, and keep extracting value. The incident trace and forked PoC both match that mechanism.
The critical breakpoint is inside Hypervisor deposit():
(uint160 sqrtPrice, , , , , , , ) = pool.globalState();
uint256 price = FullMath.mulDiv(uint256(sqrtPrice).mul(uint256(sqrtPrice)), PRECISION, 2**(96 * 2));
(uint256 pool0, uint256 pool1) = getTotalAmounts();
shares = deposit1.add(deposit0.mul(price).div(PRECISION));
if (total != 0) {
uint256 pool0PricedInToken1 = pool0.mul(price).div(PRECISION);
shares = shares.mul(total).div(pool0PricedInToken1.add(pool1));
}
Source origin: verified Hypervisor contract at 0x61a7...15e4.
This logic violates the intended invariant that a depositor should receive shares equal to the depositor's fair contribution to vault value, independent of transient same-transaction spot distortions. The same mutable spot drives both the numerator and denominator of share issuance. Because Algebra globalState() is updated by public swaps, the attacker can first move the spot, then deposit during the manipulated state, and receive an inflated share balance.
The public entrypoint is enforced by UniProxy and constrained by Clearing, but the constraints remain compatible with exploitation:
if(!positions[pos].list[from]) {
if(!p.zeroDeposit) require(deposit0 > 0 && deposit1 > 0, "must deposit to both sides");
...
}
if (twapCheck || p.twapOverride) {
checkPriceChange(pos, (p.twapOverride ? p.twapInterval : twapInterval), (p.twapOverride ? p.priceThreshold : priceThreshold));
}
if (p.depositOverride && !positions[pos].list[from]) {
require(deposit0 <= p.deposit0Max, "token0 exceeds");
require(deposit1 <= p.deposit1Max, "token1 exceeds");
}
Source origin: verified Clearing contract at 0x1f77...57f4f.
The seed trace shows the exploit sequence stayed within public components: a Balancer flash loan funded USDC, a Uniswap V3 flash funded USDT, Algebra swaps moved the spot, UniProxy deposits minted Hypervisor shares, Hypervisor withdrawals redeemed the inflated claims, and a final public WETH/USDC swap realized profit. The balance diff confirms the sender EOA gained 211903499271683579677 wei and the WETH/USDC pool lost 211906213837883579677 WETH-equivalent smallest units.
The adversary cluster contains the sender EOA 0x5351536145610aa448a8bf85ba97c71caf31909c and the helper contract 0xfd42cba85f6567fef32bab24179de21b9851b63e created and used inside the exploit transaction. The EOA signed and submitted a single transaction; the helper contract executed the flash callbacks, swaps, deposits, withdrawals, and final settlement.
The trace-backed flow is:
1. Borrow 2,000,000 USDC from Balancer Vault.
2. Borrow 3,000,000 USDT from the Uniswap V3 WETH/USDT pool.
3. Swap against the Algebra pool to move Hypervisor's observed spot price.
4. Deposit through public UniProxy with bounded public deposit sizes.
5. Withdraw inflated Hypervisor shares after reversing the price direction.
6. Repeat the oscillation/deposit/withdraw cycle to compound dilution.
7. Convert residual USDC into WETH, unwrap to ETH, and repay flash liquidity.
In the recorded incident, the attacker used a large 300000000000 USDC public deposit alongside repeated one-sided 1000000-sized deposits allowed by the configured public path. The final realization step left the incident sender with net native ETH profit and the victim-side liquidity effectively depleted.
The exploit was an ACT opportunity because no privileged keys, governance access, or private infrastructure were required. Any unprivileged actor with public chain access and enough search/simulation capability could have used the same public path under the observed state.
The measured loss captured in the artifacts is:
{
"token_symbol": "WETH",
"amount": "211906213837883579677",
"decimal": 18
}
The attacker sender EOA's native balance increased from 798711735577737800 wei to 212702211007261317477 wei, for a net gain of 211903499271683579677 wei after gas.
0x025cf2858723369d606ee3abbc4ec01eab064a97cc9ec578bf91c6908679be75 on Arbitrum.0x61a7b3dae70d943c6f2ea9ba4ffd2fecc6af15e4.0x1f1ca4e8236cd13032653391db7e9544a6ad123e.0x1f7792ed527a399159583730017cdb5003d57f4f.