# Replayable execution without consumed marker

Actions that run but never record completion, letting the same proposal, vote, or call execute again

_Area: Smart contract access control and control flow. Seen in 3 disclosed reports; latest 2025-04-10. Updated 2026-11-02._

## How it works
An action is meant to happen once, but nothing durable records that it happened. The guard that should mark it consumed is either reset too early, never written, or lives in state that a revert or a nested call discards. The assumption that breaks: "if this code ran, the system knows it ran." When the marker is missing or shared, the same input satisfies the precondition again and the effect repeats.

## Where it shows up
- Vote tallies or thresholds reset after execution, so new votes can re-meet the threshold [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-07.md).
- Per-call state (queues, pointers in `ctx.Value`) stored on an outer context and not snapshotted with the statedb, so nested calls share it [E1](https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03.md).
- Batch executors that revert atomically on any failure and persist no per-item attempted state [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md).
- Failed calls left "pending" with no expiry, replayable against later state [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md).
- Cosmos/precompile dispatch queues appended to but never cleared on revert [E1](https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03.md).

## How to review
Find the exact property: after an action's effect is applied, a durable marker must exist that makes a second attempt fail, and that marker must survive reverts and be scoped per call. Check:
- Is the tally/queue/attempt flag cleared *before* or *after* the external call, and can concurrent same-block inputs re-satisfy it? [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-07.md)
- Does nested execution get its own empty state, or inherit a pointer from the outer context? [E1](https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03.md)
- On partial failure, is per-item state persisted, or does the whole batch revert leaving items pending? [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md)
- Is there an expiry so stale items cannot execute against changed state? [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md)

## How finders spotted it
- Read the `onlySigners` modifier, noticed the vote count resets after execution, then set threshold to 1 in a unit test to show double execution [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-07.md).
- Traced the precompile dispatch flow, saw the queue pointer lives on the outer context and nested snapshots don't reset it, then built a try/catch PoC around a reverting nested call [E1](https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03.md).
- Read `CallLib.executeCalls`, saw it reverts entirely on any failed call and the executor records no attempted state, then reasoned about relayer retries [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md).

## Variants seen
- Threshold vote tally reset enabling same-proposal re-execution [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-07.md).
- Context-scoped queue shared across nested calls, surviving revert [E1](https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03.md).
- Atomic batch revert leaving failed items replayable indefinitely [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md).

## Impact and severity
Re-execution of sensitive operations: IBC transfers dispatched despite a reverted EVM call [E1](https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03.md); duplicate governance execution [E2](https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-07.md); gas-drained relayers and stale calls (e.g. unpause) firing against changed state [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md). Impact rises when the replayed action is privileged or non-idempotent, and when no expiry lets it land arbitrarily later [E3](https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md).

## Evidence
- E1: https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03.md
- E2: https://bugbountylibrary.com/r/c4%3A2023-07-axelar%3AM-07.md
- E3: https://bugbountylibrary.com/r/c4%3A2022-12-pooltogether%3AM-03.md
