Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Follow the [migration document](docs/migrations/v0.5.x_to_v0.6.0.md) for upgrade

### BUG FIXES

- Fix undercharged internal EVM execution in `CallEVMWithData` by (1) bounding the message `GasLimit` to the caller-provided `gasCap` when set (`min(gasCap, DefaultGasCap)`) instead of always using `DefaultGasCap`, and (2) charging the SDK gas meter for the actual pre-refund work (`MaxUsedGas`) rather than the post-refund `GasUsed` on non-precompile calls, preventing a refund-maximizing contract from forcing repeatable, undercharged internal EVM compute (e.g. via the CosmWasm ERC20 query bindings).
- Fix EVM fee-abstraction gas refund to compute the refund against the full transaction gas (`gasUsed + leftoverGas`) instead of `gasUsed`, bounding the refund by the paid fee and preventing the fee collector from being drained by high gas limit transactions.
- [\#15](https://github.com/KiiChain/evm/pull/15) Fix distribution precompile 32-byte withdraw address inflating native supply by skipping non-20-byte accounts when mirroring balance changes to the StateDB.

Expand Down
24 changes: 22 additions & 2 deletions x/vm/keeper/call_evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,22 @@ func (k Keeper) CallEVMWithData(ctx sdk.Context, stateDB *statedb.StateDB, from
return nil, err
}

// Bound the EVM gas limit by the caller-provided gasCap when set, falling
// back to DefaultGasCap. This prevents callers (e.g. CosmWasm query bindings)
// from triggering EVM execution larger than their remaining gas budget.
gasLimit := config.DefaultGasCap
if gasCap != nil && gasCap.IsUint64() {
if capped := gasCap.Uint64(); capped < gasLimit {
gasLimit = capped
}
}
Comment thread
mattkii marked this conversation as resolved.
Outdated

msg := core.Message{
From: from,
To: contract,
Nonce: nonce,
Value: big.NewInt(0),
GasLimit: config.DefaultGasCap,
GasLimit: gasLimit,
GasPrice: big.NewInt(0),
GasTipCap: big.NewInt(0),
GasFeeCap: big.NewInt(0),
Expand All @@ -68,7 +78,17 @@ func (k Keeper) CallEVMWithData(ctx sdk.Context, stateDB *statedb.StateDB, from
return res, errorsmod.Wrap(types.ErrVMExecution, res.VmError)
}

ctx.GasMeter().ConsumeGas(res.GasUsed, "apply evm message")
// Charge the SDK gas meter for the actual pre-refund EVM work (MaxUsedGas)
// rather than the post-refund GasUsed. Internal calls run with a full refund
// and no minimum-gas floor, so GasUsed can fall far below the real compute
// performed by validators; billing MaxUsedGas removes that undercharge.
// Precompile sub-calls keep their existing accounting.
chargedGas := res.GasUsed
if !callFromPrecompile && res.MaxUsedGas > chargedGas {
chargedGas = res.MaxUsedGas
}

ctx.GasMeter().ConsumeGas(chargedGas, "apply evm message")
Comment thread
mattkii marked this conversation as resolved.
Outdated

return res, nil
}
Loading