{"record":{"id":"e9c8f1cbeaa762c3","repo":"nautechsystems/nautilus_trader","slug":"estimated-gas-estimate-with-gas-buffer-bps-bps","errorCode":null,"errorMessage":"Estimated gas {estimate} with {gas_buffer_bps} bps buffer ({buffered}) exceeds gas limit {gas_limit}","messagePattern":"Estimated gas (.+?) with (.+?) bps buffer \\((.+?)\\) exceeds gas limit (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/transaction.rs","lineNumber":337,"sourceCode":"    );\n\n    Ok(())\n}\n\n/// Applies `gas_buffer_bps` over the `eth_estimateGas` result.\n///\n/// A buffered estimate above `gas_limit` rejects the transaction rather than clamping to the\n/// ceiling: on Arbitrum the estimate folds the L1 data fee into gas units, and clamping\n/// guarantees a paid-for out-of-gas revert.\n///\n/// # Errors\n///\n/// Returns an error if the buffered estimate exceeds `gas_limit` or the arithmetic overflows.\npub fn derive_gas_limit(estimate: u64, gas_buffer_bps: u32, gas_limit: u64) -> anyhow::Result<u64> {\n    let buffered = apply_buffer_bps(u128::from(estimate), gas_buffer_bps)?;\n\n    if buffered > u128::from(gas_limit) {\n        anyhow::bail!(\n            \"Estimated gas {estimate} with {gas_buffer_bps} bps buffer ({buffered}) exceeds gas limit {gas_limit}\"\n        );\n    }\n\n    u64::try_from(buffered).context(\"buffered gas limit overflow\")\n}\n\n/// Derives EIP-1559 fees from the latest base fee and the node's suggested priority fee.\n///\n/// `max_fee_per_gas` is the base fee with `base_fee_buffer_bps` applied plus the priority fee;\n/// `max_priority_fee_per_gas` is the priority fee itself. `max_fee_per_gas_wei` is a hard\n/// ceiling that rejects the transaction when current conditions exceed it.\n///\n/// # Errors\n///\n/// Returns an error if the derived max fee exceeds `max_fee_per_gas_wei` or the arithmetic\n/// overflows.\npub fn derive_fees(","sourceCodeStart":319,"sourceCodeEnd":355,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/transaction.rs#L319-L355","documentation":"derive_gas_limit applies a basis-point buffer to a gas estimate and checks the result against a configured gas_limit ceiling. It bails when the buffered estimate exceeds the ceiling (or when the buffer arithmetic overflows in apply_buffer_bps). This prevents submitting transactions whose declared gas limit is above the allowed maximum.","triggerScenarios":"Calling derive_gas_limit(estimate, gas_buffer_bps, gas_limit) where estimate * (1 + gas_buffer_bps/10000) > gas_limit, e.g. a large simulation estimate, an oversized buffer in bps, or a too-low configured gas_limit. Also raised via prepare_and_sign_with_anchors when building a transaction.","commonSituations":"Network congestion pushing estimates above a static gas_limit cap; a buffer configured too aggressively (e.g. 5000 bps = 50%); gas_limit configured from an outdated chain or block-gas setting; a pathological contract path consuming far more gas than the ceiling allows.","solutions":["Raise the configured gas_limit to at least the buffered estimate, if the ceiling is safe to raise.","Reduce gas_buffer_bps so the buffered estimate fits under the ceiling.","Investigate why the estimate is high: re-simulate the call, check for unexpectedly expensive contract paths or failing simulations.","If the estimate genuinely exceeds the chain-safe maximum, abort the transaction rather than clamping — do not submit with a gas limit below the estimate."],"exampleFix":"// before\nlet gas = derive_gas_limit(estimate, 5000, 300_000)?; // buffered 750k > 300k ceiling\n// after\nlet gas = derive_gas_limit(estimate, 1000, 1_000_000)?; // buffer and ceiling sized for the workload","handlingStrategy":"validation","validationCode":"fn buffered_gas_ok(estimate: u64, gas_buffer_bps: u32, gas_limit: u64) -> bool {\n    let buffered = estimate as u128 * (10_000 + gas_buffer_bps as u128) / 10_000;\n    buffered <= gas_limit as u128\n}\n// check before calling derive_gas_limit / prepare_and_sign_with_anchors","typeGuard":null,"tryCatchPattern":"match derive_gas_limit(estimate, bps, limit) {\n    Err(e) if e.to_string().contains(\"exceeds gas limit\") => /* raise gas_limit, lower bps, or abort the tx */,\n    Err(e) => return Err(e),\n    Ok(gas) => gas,\n}","preventionTips":["Size gas_limit ceilings from recent block/contract gas usage, not stale values","Re-simulate and re-estimate under current network conditions before signing","Keep gas_buffer_bps modest (e.g. 10-20%) and reconcile against the ceiling in config validation","Monitor estimate-vs-ceiling headroom and alert before it hits zero"],"tags":["rust","gas","configuration","overflow"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}