# ExecuteRequest’s are not properly removed from the context queue

Initia minievm cosmos precompile queued ExecuteRequests in outer context; a reverted EVM call caught by try/catch still dispatched its Cosmos messages, executing sensitive ops like IBC transfers.

- Payout: Contest reward
- Severity: high
- Program: Initia
- Credited: berndartmueller
- Disclosed: 2025-04-10
- Write-up quality: 8/10
- Original: https://code4rena.com/reports/2025-02-initia-cosmos#h-03
- Library page: https://bugbountylibrary.com/r/c4%3A2025-02-initia-cosmos%3AH-03
- Tags: domain:web3 impact:funds-loss impact:integrity kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:chained technique:source-review vuln:accounting-error vuln:business-logic

**Target:** minievm cosmos precompile (x/evm/precompiles/cosmos) ExecuteRequest queue
**Root cause:** prepareSDKContext sets the ExecuteRequest queue pointer on the outer context; nested EVM calls creating a new statedb snapshot don't get their own empty queue, so the precompile appends to the outer queue which is never cleared on revert.
**Steps:**
1. Add external function `nested(n)` to Counter.sol that calls `COSMOS_CONTRACT.execute_cosmos(_recursive(n))` then `revert()`.
2. In `recursive(n)`, wrap `try this.nested(n) {} catch {}` so the revert is swallowed.
3. Recompile contracts with `make contracts-gen`.
4. Deploy Counter via `EVMCreate`, call `recursive(1)` via `EVMCall`.
5. Observe `logs` length is 2: the dispatched MsgCall executes despite the inner revert.
**How found:** Code review of the cosmos precompile and EVMCallWithTracer dispatch flow; noticed the queue is a pointer stored on the outer context and that nested EVM snapshots don't reset it, then built a PoC with try/catch around a reverting nested call.
**Exploitation:** A Solidity contract dispatches a Cosmos SDK message (e.g. IBC token transfer) via the cosmos precompile, then reverts inside a try/catch. The queued ExecuteRequest survives in the outer context and is dispatched after the outer EVM call succeeds, executing the sensitive message even though the contract logic intended it only on success.
**Insight:** When auditing precompile/context-queue patterns, check whether per-call state (queues, pointers in ctx.Value) is snapshotted alongside statedb; a pointer stored on the outer context is shared across nested EVM frames and survives reverts caught by try/catch.
