For the complete documentation index, see llms.txt. This page is also available as Markdown.

74604 sc low system pause disables verifier kill switch allowing unchecked dispute progression

Submitted on Apr 23rd 2026 at 18:46:24 UTC by @magtentic for Audit Comp | Base Azul

  • Report ID: #74604

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/base/contracts/tree/v8.1.0/src/multiproof

  • Impacts:

    • Circumventing the dispute/challenge mechanism to prevent correction of an invalid proposal before finalization

Description

Brief/Intro

During an emergency pause, dispute games are marked “improper,” which disables Verifier.nullify(). However, dispute entry points (initializeWithInitData, verifyProposalProof, challenge) do not check the pause state. An attacker can keep submitting fraudulent games or proofs while paused, and the global kill-switch (nullify) will revert until unpause. Thus the pause intended to stop activity actually blocks the defender’s ability to nullify dishonest games.

Vulnerability Details

Verifier.nullify() requires the caller game to satisfy ANCHOR_STATE_REGISTRY.isGameProper(...) and isGameRespected(...).

    function nullify() external override {
        if (
            !ANCHOR_STATE_REGISTRY.isGameProper(IDisputeGame(msg.sender))
                || !ANCHOR_STATE_REGISTRY.isGameRespected(IDisputeGame(msg.sender))
        ) revert NotProperGame();
...

In AnchorStateRegistry.isGameProper, one condition is if (paused()) return false;.

Thus, when the system is paused, all games are “not proper,” and any nullify() call reverts NotProperGame().

Meanwhile, functions like challenge() or verifyProposalProof() have no whenNotPaused guard (no paused() check is present), so attackers can continue to challenge or submit proofs during the pause.

In effect, the automated defense is disabled exactly when it’s needed. Once the pause is lifted, the malicious games become “proper” again and can finalize unless manually blacklisted.

Pausing is a normal protocol operation, but the attack does not rely on triggering the pause. The issue is that once the system is legitimately paused, unprivileged users can still submit new games and proofs, while nullify() is disabled by the same pause state.

Impact Details

This allows an attacker to exploit a paused system window: if a prover (or enclave) is compromised or a proof scheme is broken resulting in a pause, the attacker can continuously create malicious games during pause. Legitimate players cannot pause these games via nullify().

After unpausing, these games might lead to invalid finalization or forced anchor updates.

The impact is a bypass of intended emergency protections, an in-scope “circumventing dispute/challenge mechanism” scenario, potentially with serious downstream consequences on L1 state.

References

Verifier AnchorStateRegistry

The nullify() function checks isGameProper(...) and isGameRespected(...).

In the AnchorStateRegistry, isGameProper(...) returns false if paused() == true.

Note that closeGame() explicitly checks paused() and reverts (as intended),

but challenge() (the dispute path) has no such pause check.

Pausing is part of the normal processes as part of the contract and requires no attack path

Proof of Concept

Copy the below PoC to test/VerifierPauseKillSwitch.t.sol

Run the below to execute

Was this helpful?