Skip to content

[scanner] No type-level guard prevents pre-signing on OracleUpdate with new_price = None #231

@obchain

Description

@obchain

Refs #46

PR: feat/21-mempool-monitor
File: crates/charon-scanner/src/mempool.rs
Types: OracleUpdate, PreSignedLiquidation, PendingCache::insert()

Problem

OracleUpdate.new_price is Option: None for updatePrice and updateAssetPrice (single-arg refresh calls that do not carry the new price in calldata), Some(price) for setDirectPrice and setUnderlyingPrice.

The doc comment on new_price states the caller "must re-read the oracle after the tx confirms" for the None case. However, PendingCache::insert() accepts any PreSignedLiquidation unconditionally. Nothing prevents a caller from inserting a pre-signed liquidation triggered by an OracleUpdate with new_price = None.

updatePrice and updateAssetPrice are the calls made by the ResilientOracle's push-based keepers — they are the MOST COMMON oracle update type. Pre-signing a liquidation against a None price update means the pre-sign was built against the current (pre-update) price, which is the wrong state. If the update is a price decrease, the pre-sign may liquidate a currently-healthy borrower.

Required fix

Option A: Make OracleUpdate an enum to structurally distinguish the two cases:

pub enum OracleUpdate {
    Refresh { tx_hash: B256, selector: FixedBytes<4>, asset: Address },
    DirectUpdate { tx_hash: B256, selector: FixedBytes<4>, asset: Address, price: U256 },
}

This forces downstream code to explicitly handle the Refresh variant and prevents accidental pre-signing.

Option B: At minimum, add a runtime guard in the downstream handler that skips PendingCache::insert() when new_price is None, with a prominent doc comment on insert() stating this contract.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglayer:rustRust crates (core / scanner / protocols / executor / cli)priority:p1-coreCore MVP scope

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions