Skip to content

[executor] Simulator::sender not tied to TxBuilder signer — onlyOwner fails simulation, all opportunities silently dropped #162

@obchain

Description

@obchain

PR: #41 (feat/executor: transaction builder + eth_call simulator)
File: crates/charon-executor/src/simulation.rs, crates/charon-executor/src/builder.rs
Refs #41

Problem

Simulator::new(sender, liquidator) and TxBuilder::new(signer, chain_id, liquidator) are constructed independently. Nothing prevents a caller from passing a different sender to the simulator than the signer address used in build_tx.

CharonLiquidator.executeLiquidation is onlyOwner. If Simulator::sender is any address other than the deployed contract's owner (e.g., zero address, wrong address, stale address after wallet rotation), every simulate() call will revert on the onlyOwner modifier and return Err. The pipeline drops every opportunity — not because the liquidation would fail, but because the simulation called from the wrong address.

The inverse failure: sender coincidentally passes onlyOwner but does not match the signer key used in build_tx. Simulation passes, real broadcast fails onlyOwner at submission.

Impact

Either all opportunities are silently dropped (simulation always fails) or simulation gives a false-pass signal (wrong sender passes onlyOwner). Both break the CLAUDE.md invariant that the eth_call gate must faithfully gate the real broadcast.

Fix

Expose a factory method that derives Simulator directly from TxBuilder to eliminate the wiring gap:

impl Simulator {
    pub fn from_builder(builder: &TxBuilder, liquidator: Address) -> Self {
        Self {
            sender: builder.signer_address(),
            liquidator,
        }
    }
}

Add a debug-mode assertion that sender != Address::ZERO. Document in rustdoc that sender must equal the CharonLiquidator owner.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglayer:rustRust crates (core / scanner / protocols / executor / cli)pr-reviewFindings from PR review processpriority:p1-coreCore MVP scopestatus:readyScoped and ready to pick up

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions