• Decide whether a reverted write ran out of gas or was refused by the contract (MK-035).

    Why this exists. The SDK returns { hash } without awaiting the receipt, by design, so a revert that happens after a passing simulation is something the caller discovers later and previously had no way to classify. Nothing in the error surface distinguished exhaustion from refusal, and the two call for opposite responses.

    What evidence a consumer actually has, without a tracing endpoint, established rather than assumed:

    1. gasUsed === gasLimit. Conclusive for exhaustion, but ONLY at the top level. The EVM forwards at most 63/64 of the remaining gas to a nested call, so an inner frame can exhaust its allowance while the outer frame keeps the last 1/64. A traced occurrence of exactly that showed gasUsed 710023 against gasLimit 720980.
    2. Re-executing the same call at the mined block. If it reverts WITH a reason, the contract refused and the reason is the answer. This is the strong case.
    3. If the re-execution does NOT revert, that is genuinely ambiguous. eth_call at a block number runs against END of block state, after the failing transaction and everything else in it, so a condition that was true mid block is invisible to it. It is consistent with a nested out of gas AND with a race the caller lost.

    Case 3 returns INDETERMINATE, and that is not a hedge: it is the honest boundary of what is knowable here. debug_traceTransaction settles it, and most public endpoints do not expose it. The advice for that case says so.

    Parameters

    • publicClient: {}
    • hash: `0x${string}`

    Returns Promise<WriteDiagnosis>