Skip to content

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

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

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

Conversation

@ygd58

@ygd58ygd58 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 exacteth_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-actionsBot changed the base branch from main to v2-devAugust 7, 2026 11:32
@github-actions

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

coderabbitaiBot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: 3fb14585-fc6c-41c1-b4c0-53d39890102e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 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 nameStatusExplanation
Title check✅ PassedThe title clearly and concisely identifies the explicit gas override added to writeContract and deployContract.
Description check✅ PassedThe description clearly covers the change, rationale, implementation details, and testing results, but it omits several template sections and checklist items.
Docstring Coverage✅ PassedNo functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck 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.

@coderabbitaicoderabbitaiBot 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 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.

_sendTransaction accepted any bigint for the gas override, including
0n or a negative value. Zero can't execute an EVM transaction, and a
negative value would reach the external-wallet request as an invalid
hex string like "0x-1".
Added a check right alongside the existing early validations
(consensus contract address, empty transaction variants) in
_sendTransaction, before any transaction preparation happens.
Added tests for both 0n and -1n, confirming the error is thrown
before eth_estimateGas or signTransaction are ever called. Full
suite: 89 passed. eslint: clean.
Sign up for freeto 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

@ygd58