Skip to content

feat: add explicit gas override to writeContract/deployContract - #205

Open
ygd58 wants to merge 1 commit into
genlayerlabs:v2-devfrom
ygd58:feat/explicit-gas-override
Open

feat: add explicit gas override to writeContract/deployContract#205
ygd58 wants to merge 1 commit into
genlayerlabs:v2-devfrom
ygd58:feat/explicit-gas-override

Conversation

@ygd58

@ygd58 ygd58 commented Aug 7, 2026

Copy link
Copy Markdown

Summary

Adds the second part of #402's ask: an explicit gas override for writeContract/deployContract, bypassing eth_estimateGas entirely.

Context

#402 reports that an exact eth_estimateGas result was used as the outer EVM gas limit on Bradbury, and the resulting transaction reverted twice — identical calldata succeeded when replayed with a larger explicit limit. No way existed to override the estimate.

On the automatic-headroom part of the ask: this repo already has withTransactionGasHeadroom (a 2x margin over the estimate), which would cover the exact numbers in #402's repro (1,319,997 estimated → 2,639,994 with headroom, comfortably above the 2,000,000 that #402 confirmed works). I checked the actual genlayer-js@1.1.8 tarball from the npm registry directly and confirmed this headroom code isn't in the published package yet — so that part of the fix exists but hasn't shipped. This PR is the complementary, still-needed part: a caller-side override for cases even the headroom doesn't cover, or for callers who just want deterministic control over gas.

Change

Added an optional gas?: bigint to writeContract and deployContract's options. When provided:

  • eth_estimateGas is not called at all
  • no headroom markup is applied
  • the value is used exactly as given, on both the local-account (signTransaction) and external-wallet (eth_sendTransaction) send paths

Both functions already funnel through a shared _sendTransactionsendWithEncodedData helper, so this was a single plumbing point for both.

Testing

Added 4 cases to tests/contracts-actions.test.ts, reusing the existing setupWriteContractHarness:

  • explicit override bypasses eth_estimateGas entirely and is used as-is
  • omitting the override still estimates and applies headroom — asserts the exact 2_639_994n value from #402's own numbers (1_319_997 * 20_000bps / 10_000)
  • the override threads through deployContract the same way as writeContract

Full suite: 87 passed. eslint: clean on all changed files.

Summary by CodeRabbit

  • New Features

    • Added optional gas limit overrides for contract write and deployment transactions.
    • Transactions with an explicit gas limit skip automatic gas estimation.
    • Existing automatic estimation and safety headroom remain unchanged when no override is provided.
  • Tests

    • Added coverage confirming explicit gas limits are preserved and default estimation continues to work.

An exact eth_estimateGas result can itself cause the outer
addTransaction EVM transaction to revert before GenVM is reached —
confirmed on Bradbury (#402): gas limit 1,319,997 (== a fresh
eth_estimateGas result) reverted twice; replaying identical calldata
with 2,000,000 succeeded and finalized normally. No caller-side way
existed to work around a bad estimate.

Note: this repo's automatic gas headroom (withTransactionGasHeadroom,
a 2x margin) already covers the specific numbers in #402's repro, but
it isn't published to npm yet — I checked the actual genlayer-js@1.1.8
tarball from the registry and confirmed the headroom code isn't in it.
This change adds the second, complementary part of #402's ask: a way
to bypass estimation entirely for cases the headroom doesn't cover.

Added an optional `gas?: bigint` field to writeContract and
deployContract. When provided, it's used exactly as given — no
eth_estimateGas call, no headroom markup — since an explicit override
is the caller stating what to use. Both local-account (signTransaction)
and external-wallet (eth_sendTransaction) send paths respect it; both
flow through the same shared `_sendTransaction`/`sendWithEncodedData`
helper that writeContract and deployContract already share, so there
was a single spot to plumb this through for both.

Tests: added 4 cases to tests/contracts-actions.test.ts using the
existing setupWriteContractHarness — override bypasses estimation
entirely, no-override path still estimates+applies headroom (asserting
the exact 2,639,994 = 1,319,997 * 2x from #402's numbers), and the
override threads through deployContract the same way. Full suite: 87
passed. eslint: clean.
@github-actions
github-actions Bot changed the base branch from main to v2-dev August 7, 2026 11:32
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

This PR targeted main, which is only the default/static branch.

I retargeted it to v2-dev, the active development branch. Pushes to v2-dev automatically fast-forward main.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The contract client now accepts optional explicit gas limits for writeContract and deployContract. Explicit values bypass estimation and headroom. Transactions without overrides retain existing estimation, fallback, and headroom behavior.

Changes

Gas override support

Layer / File(s) Summary
Public gas override API
src/types/clients.ts, src/contracts/actions.ts
writeContract and deployContract now accept optional gas values and forward them to _sendTransaction.
Transaction gas selection and validation
src/contracts/actions.ts, tests/contracts-actions.test.ts
_sendTransaction uses explicit gas unchanged. Without an override, it estimates gas and applies the existing 200% headroom and fallback behavior. Tests cover both paths.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ContractAction as writeContract/deployContract
  participant SendTransaction as _sendTransaction
  participant EthEstimateGas as eth_estimateGas
  participant SignedTransaction as signed transaction
  ContractAction->>SendTransaction: pass optional gas override
  alt gas override provided
    SendTransaction->>SignedTransaction: use explicit gas unchanged
  else gas override absent
    SendTransaction->>EthEstimateGas: estimate gas
    EthEstimateGas-->>SendTransaction: estimated gas
    SendTransaction->>SignedTransaction: use estimated gas with 200% headroom
  end
Loading

Possibly related PRs

Suggested reviewers: muncleuscles, cristiam86

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the explicit gas override added to writeContract and deployContract.
Description check ✅ Passed The description clearly covers the change, rationale, implementation details, and testing results, but it omits several template sections and checklist items.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/contracts/actions.ts`:
- Around line 2062-2064: Update _sendTransaction to validate gasOverride before
transaction preparation, accepting only bigint values greater than 0n and
rejecting 0n or negative overrides with the existing validation error behavior.
Add coverage for both zero and negative gasOverride values.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8763eea8-2496-43ce-a29f-67486f2497bb

📥 Commits

Reviewing files that changed from the base of the PR and between 1b7f50a and 5714994.

📒 Files selected for processing (3)
  • src/contracts/actions.ts
  • src/types/clients.ts
  • tests/contracts-actions.test.ts

Comment thread src/contracts/actions.ts
Comment on lines +2062 to +2064
if (gasOverride !== undefined) {
estimatedGas = gasOverride;
} else {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reject non-positive gas overrides.

A caller can pass 0n or a negative bigint. A negative value reaches the external-wallet request as an invalid value such as 0x-1. A zero value cannot execute an EVM transaction.

Validate gasOverride > 0n in _sendTransaction before transaction preparation. Add tests for 0n and a negative value.

Proposed fix
+  if (gasOverride !== undefined && gasOverride <= 0n) {
+    throw new Error("gas must be greater than zero.");
+  }
+
   const sendWithEncodedData = async (transactionVariant: EncodedTransactionVariant) => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/contracts/actions.ts` around lines 2062 - 2064, Update _sendTransaction
to validate gasOverride before transaction preparation, accepting only bigint
values greater than 0n and rejecting 0n or negative overrides with the existing
validation error behavior. Add coverage for both zero and negative gasOverride
values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant