Skip to content

[executor] resync() has no high-water-mark guard — can reissue nonces for in-flight txs #185

@obchain

Description

@obchain

Summary

NonceManager::resync() re-fetches the on-chain pending transaction count and resets the local atomic counter to that value. This is incorrect when a tx was broadcast successfully (reached at least one BSC node) but the originating RPC call returned a transport error — common with BSC's high-redundancy public RPC pools where a request times out but the tx has already propagated.

Sequence of failure:

  1. next() issues nonce N, tx is signed and sent
  2. RPC returns a timeout error on the broadcast call
  3. resync() fires, fetches pending_count = N (tx not yet reflected in pending state)
  4. next() issues nonce N again for the next opportunity
  5. Two signed liquidation txs with nonce N are now in the mempool — whichever has higher max_fee wins, the other is silently dropped

The fix is a high-water mark: the maximum nonce ever issued by next(). resync should set the counter to max(on_chain_pending, high_water + 1).

File

crates/charon-executor/src/nonce.rsNonceManager::resync()

Fix

pub struct NonceManager {
    nonce: Arc<AtomicU64>,
    high_water: Arc<AtomicU64>,  // highest nonce ever issued by next()
}

pub fn next(&self) -> u64 {
    let n = self.nonce.fetch_add(1, Ordering::SeqCst);
    self.high_water.fetch_max(n, Ordering::SeqCst);
    n
}

pub async fn resync(&self, provider: &impl Provider) -> Result<(), NonceError> {
    let on_chain = /* pending count */;
    let hw = self.high_water.load(Ordering::SeqCst);
    let safe = on_chain.max(hw + 1);
    self.nonce.store(safe, Ordering::SeqCst);
    Ok(())
}

Refs #43

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