flagOutcome(CORRUPTED, ...) is meant to reflect a genuine security breach, confirmed by the moderator's off-chain judgement against the live AttackRegistry's CORRUPTED state. The permissionless claimExpired() auto-resolution fallback exists purely as a backstop for a PERMANENTLY-ABSENT moderator, scope-blind by design and documented as staker-pessimistic but rare in practice.
The registry's CORRUPTED signal is set via AttackRegistry.markCorrupted(), gated only by onlyAttackModerator -- a role that defaults to the agreement's OWNER at registration, with zero on-chain proof of an exploit required. Since ConfidencePoolFactory.createPool requires the Sponsor to be the Agreement owner, the Sponsor is -- by default -- the same address authorized to unilaterally flip their OWN agreement to CORRUPTED, after just one routine DAO approveAttack() call.
Critically, this does NOT require the pool's own outcomeModerator to be deceived or complicit at all: if the moderator simply does nothing, the permissionless claimExpired() auto-CORRUPTED fallback mechanically finalizes bad-faith CORRUPTED on its own once expiry + MODERATOR_CORRUPTED_GRACE (180 days) elapses -- callable by anyone, including the Sponsor. The moderator's only defense is to PROACTIVELY investigate and flag SURVIVED (explicitly permitted even when the registry shows CORRUPTED, as the "out of scope" escape hatch) before that window closes -- amplified further since a single markCorrupted() call compromises every pool backed by the same agreement.
Verified live on BattleChain testnet right now: bondToken/verifiedBondAmount/feeAmount are all zero (path is free), and the project's own demo agreement (already DAO-approved, UNDER_ATTACK) already has attackModerator == owner.
Likelihood:
Reason 1 Confirmed live right now: bondToken, verifiedBondAmount, and feeAmount are all zero on the real BattleChain testnet BondManager -- the entire path is free. Confirmed live on the project's own real, DAO-approved demo agreement (currently UNDER_ATTACK): getAttackModerator() returns the exact same address as owner().
Reason 2 The attack succeeds even with a completely passive pool moderator -- no deception, no complicity required. Every pool where the moderator doesn't proactively investigate and flag SURVIVED within 180 days of expiry resolves this way automatically, amplified for free across every pool the Sponsor backs with the same self-corrupted agreement.
Impact:
Impact 1 Steals stakers' full LOCKED PRINCIPAL, not just bonus -- once risk genuinely opens, withdraw() is permanently disabled, so stakers can't protect themselves even after real risk is confirmed on-chain.
Impact 2 Requires zero ongoing cooperation from any honest party after the initial routine DAO approval -- the mechanical 180-day auto-resolve path means the Sponsor doesn't even need to successfully deceive anyone, just wait out a passive moderator.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.