Skip to content

fix: cosmwasm evm query path repeatable undercharged evm exec#345

Open
mattkii wants to merge 3 commits into
mainfrom
fix/wasm-repeatable-undercharged-internal-evm-exec
Open

fix: cosmwasm evm query path repeatable undercharged evm exec#345
mattkii wants to merge 3 commits into
mainfrom
fix/wasm-repeatable-undercharged-internal-evm-exec

Conversation

@mattkii

@mattkii mattkii commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes a gas-accounting vulnerability in the CosmWasm→EVM query bridge
(wasmbinding/evm/queries.go). Any CosmWasm contract could call the ERC20
information/balance/allowance queries against an arbitrary EVM contract, and each
sub-call was issued with gasCap=nil. The underlying EVM helper ignores a nil cap
and falls back to DefaultGasCap (25M), so an attacker-controlled ERC20 could force
large, repeatable internal EVM execution while the SDK gas meter was charged only the
post-refund amount — enabling sustained, undercharged validator compute.

This PR makes every internal ERC20 query sub-call pass a real gas cap bounded by the
transaction's remaining SDK gas (and DefaultGasCap), mirroring the existing
buildEthCallRequest behaviour used by the generic EthCall path.

Changes:

  • Add queryGasCap(ctx) helper returning min(ctx.GasMeter().GasRemaining(), DefaultGasCap).
  • Pass queryGasCap(ctx) instead of nil to all six sub-calls: decimals, name,
    symbol, totalSupply, balanceOf, allowance.

Dependencies: full mitigation also relies on the companion KiiChain/evm PR
(fix/wasm-repeatable-undercharged-internal-evm-exec) where CallEVMWithData now
honours the gas cap and bills the SDK meter for actual pre-refund EVM work. That fork
version must be published and the replace github.com/cosmos/evm => github.com/KiiChain/evm
directive in go.mod bumped for the fix to take full effect on-chain.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • go test -tags=test ./wasmbinding/evm/... — all query binding tests pass (incl. ERC20 information/balance/allowance and EthCall gas tests).
  • go build ./wasmbinding/... — compiles cleanly.

PR Checklist:

  • Updated changelog with PR's intent
  • Lint with make lint-fix (golangci-lint v2.7.2, 0 issues)

@mattkii mattkii requested a review from jhelison as a code owner June 25, 2026 05:11
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@mattkii, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 34 minutes and 56 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 98f74f5a-a5f4-42f7-92c4-7c5022ef46b2

📥 Commits

Reviewing files that changed from the base of the PR and between 7f25e71 and 47b3f14.

📒 Files selected for processing (1)
  • .github/workflows/test.yml

Walkthrough

The PR updates ERC20-related EVM query handlers to pass a bounded gas cap into internal ABI calls instead of nil. A helper computes the cap from remaining SDK gas and emvconfig.DefaultGasCap. The changelog adds a note describing the fix.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main fix: a gas-accounting issue in the CosmWasm EVM query path.
Description check ✅ Passed The description directly explains the ERC20 query gas-cap fix and its intent.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/wasm-repeatable-undercharged-internal-evm-exec

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.

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why were these changes required?

Comment on lines +306 to +312
// queryGasCap returns the gas cap to apply to internal EVM query sub-calls.
// It is bounded by the transaction's remaining SDK gas so that a CosmWasm
// contract cannot force more EVM computation than its transaction pays for,
// and additionally capped by DefaultGasCap to match the eth_call behaviour.
func queryGasCap(ctx sdk.Context) *big.Int {
return new(big.Int).SetUint64(min(ctx.GasMeter().GasRemaining(), emvconfig.DefaultGasCap))
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Interesting approach. Would it not be better to just keep the GasRemaining? I'm saying this because the evm side with the new changes, we kind of already take the minimum

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Check if the suggestion at KiiChain/evm#18 (comment) make sense

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.

2 participants