Reproduced Exploit
Myriad: An oracle-voided market (outcome -1) resolves without setting voidedPayouts
Chain
Other
Category
untagged
Date
Jan 1970
Source
AuditVault
EVM Playground
Source-level debugger — step opcodes and Solidity in sync
The attack is replayed in an in-browser EVM preloaded with the exact dumped fork state. The execution tree shows every call; step by Solidity line or by opcode across all depths — source, Stack, Memory, Storage, Balances (native / ERC-20 / NFT), Transient storage and Return value stay in sync. Click a tree node, opcode, or source line to jump. No backend, no live RPC.
Source & credit. Reproduction of a public audit finding curated by AuditVault — the original finding: 65418-oracle-void-outcome-leaves-predictionmarketv3managerclobvoid. Standalone Foundry PoC and full write-up: 65418-oracle-void-outcome-leaves-predictionmarketv3managerclobvoid_exp in the
evm-hack-registrymirror.
Vulnerability classes: vuln/locked-funds · vuln/price
Reproduction: a faithful minimal reproduction of the vulnerable finding — the vulnerable function is reproduced verbatim (marked
@>) with faithful minimal doubles; local deploy, no fork.
Root cause#
An oracle-voided market (outcome -1) resolves without setting voidedPayouts, so every position holder's collateral (1e18) is permanently frozen in ConditionalTokens because redeemVoided reverts on require(0+0==1e18).
(int256 outcome, bool resolved) = IMarketOracle(market.oracle).getResult(marketId);
require(resolved, "oracle: not resolved");
require(outcome == 0 || outcome == 1 || outcome == -1, "invalid outcome"); // @> accepts -1 (VOIDED) but never sets voidedPayouts[marketId], leaving it [0,0]
market.resolvedOutcome = outcome; // can be -1
Why it's exploitable here#
An oracle-voided market (outcome -1) resolves without setting voidedPayouts, so every position holder's collateral (1e18) is permanently frozen in ConditionalTokens because redeemVoided reverts on require(0+0==1e18).
Attack path#
Marked-line walkthrough (Playground)#
The EVM Playground pins each step to the exact executed source line in 0x671d353a77…:
- L139 — Store market collateral: Setup: records the market's collateral token at creation.
- L149 — Void outcome accepted, no payout set: Root cause: resolution accepts void outcome
-1as valid, but the void branch never setsvoidedPayouts, leaving a voided market with no redeemable payout. - L151 — Save resolved outcome: Stores the resolved outcome (including
-1) yet writes no payout split for the void case. - L162 — Payouts must sum to 1e18: Redemption requires payouts sum to
1e18; for a void market both are 0, so0+0==1e18fails andredeemVoidedreverts. - L173 — Load market from storage: Setup: loads the target
Marketfrom storage during resolve/redeem. - L192 — Fixed manager variant: Setup: the corrected manager contract used for comparison.
- L208 — Markets storage mapping: Setup: maps each
marketIdto itsMarketrecord.
PoC#
Registry (Foundry, local deploy — verbatim vulnerable source + harm-asserting test + negative control):
cd 65418-oracle-void-outcome-leaves-predictionmarketv3managerclobvoid_exp
forge test -vvv
The browser Playground replays the same synthetic opcode-for-opcode and measures the harm: An oracle-voided market (outcome -1) resolves without setting voidedPayouts, so every position holder's collateral (1e18) is permanently fro. Both gates are green (registry forge test PASS + Playground _verify-poc VERDICT: PASS).
Sources & further analysis#
Reproductions & code
- Standalone PoC + full trace: 65418-oracle-void-outcome-leaves-predictionmarketv3managerclobvoid_exp (evm-hack-registry mirror).
- AuditVault finding: 65418-oracle-void-outcome-leaves-predictionmarketv3managerclobvoid.
- Upstream DeFiHackLabs PoC directory: src/test.
Alerts & third-party analyses
- DeFiHackLabs incident explorer: search "Myriad: An oracle-voided market (outcome -1) resolves without setting voidedPayouts".
- Web3Sec X hacked database: search.
- Rekt leaderboard: search.
- Solodit incident search: search.
These dashboards index community alerts tweets, post-mortems, and independent write-ups. Reach them through the protocol name above to cross-check this reproduction against other analyses.