diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e17a49cb..53514b6fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,7 +89,8 @@ needed to include double quotes around the hexadecimal string. - [#2177](https://github.com/NibiruChain/nibiru/pull/2177) - fix(cmd): Continue from #2127 and unwire vesting flags and logic from genaccounts.go - [#2176](https://github.com/NibiruChain/nibiru/pull/2176) - tests(evm): add dirty state tests from code4rena audit - [#2180](https://github.com/NibiruChain/nibiru/pull/2180) - fix(evm): apply gas consumption across the entire EVM codebase at `CallContractWithInput` - +- [#2183](https://github.com/NibiruChain/nibiru/pull/2183) - fix(evm): bank keeper extension gas meter type +- #### Nibiru EVM | Before Audit 2 - 2024-12-06 The codebase went through a third-party [Code4rena diff --git a/x/evm/keeper/bank_extension.go b/x/evm/keeper/bank_extension.go index 587135ac2..5531b9c5c 100644 --- a/x/evm/keeper/bank_extension.go +++ b/x/evm/keeper/bank_extension.go @@ -185,24 +185,20 @@ func (bk NibiruBankKeeper) ForceGasInvariant( // Assign vars for the tx gas meter gasMeterBefore := ctx.GasMeter() // Tx gas meter MUST be defined gasConsumedBefore := gasMeterBefore.GasConsumed() - // Don't modify the "ctx.BlockGasMeter()" directly because this is - // handled in "BaseApp.runTx" - - // Start baseGasConsumed at 0 in case we panic before BaseOp completes and - // baseGasConsumed gets a value assignment baseOpGasConsumed := uint64(0) defer func() { + // NOTE: we have to refund the entire gasMeterBefore because it's modified by AfterOp + // stateDB.getStateObject() reads from state using the local root ctx which affects the gas meter gasMeterBefore.RefundGas(gasMeterBefore.GasConsumed(), "") gasMeterBefore.ConsumeGas(gasConsumedBefore+baseOpGasConsumed, "NibiruBankKeeper invariant") }() - // Note that because the ctx gas meter uses private variables to track gas, - // we have to branch off with a new gas meter instance to avoid mutating the - // "true" gas meter (called GasMeterBefore here). - // We use an infinite gas meter because we consume gas in the deferred function - // and gasMeterBefore will panic if we consume too much gas. - ctx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter()) + // We keep the same gas meter type but reset the gas consumed prior to measuring the base op + // We need the same gas meter type because we use a custom FixedGasMeter for oracle votes in the AnteHandler + // In the defer function, we reset the gas meter again and then add the gasConsumedBefore to baseOpGasConsumed, + // so any modifications to the gasMeterBefore after this point will be inconsequential. + ctx.GasMeter().RefundGas(gasConsumedBefore, "reset gas meter before measuring base op") err := BaseOp(ctx) baseOpGasConsumed = ctx.GasMeter().GasConsumed()