Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(evm): ensure stateDB is nil after tx execution #2173

Merged
merged 4 commits into from
Jan 21, 2025
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ needed to include double quotes around the hexadecimal string.
- [#2169](https://github.com/NibiruChain/nibiru/pull/2169) - fix(evm): Better handling erc20 metadata
- [#2170](https://github.com/NibiruChain/nibiru/pull/2170) - chore: Remove redundant allowUnprotectedTxs
- [#2172](https://github.com/NibiruChain/nibiru/pull/2172) - chore: close iterator in IterateEpochInfo
-
- [#2173](https://github.com/NibiruChain/nibiru/pull/2173) - fix(evm): clear `StateDB` between calls

#### Nibiru EVM | Before Audit 2 - 2024-12-06

The codebase went through a third-party [Code4rena
Expand Down
5 changes: 3 additions & 2 deletions x/evm/keeper/funtoken_from_coin.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ func (k *Keeper) deployERC20ForBankCoin(
if stateDB == nil {
stateDB = k.NewStateDB(ctx, txConfig)
}
defer func() {
k.Bank.StateDB = nil
}()
evmObj := k.NewEVM(ctx, evmMsg, evmCfg, nil /*tracer*/, stateDB)
evmResp, err := k.CallContractWithInput(
ctx, evmObj, evm.EVM_MODULE_ADDRESS, nil, true /*commit*/, input, Erc20GasLimitDeploy,
Expand All @@ -110,8 +113,6 @@ func (k *Keeper) deployERC20ForBankCoin(
if err != nil {
return gethcommon.Address{}, errors.Wrap(err, "failed to commit stateDB")
}
// Don't need the StateDB anymore because it's not usable after committing
k.Bank.StateDB = nil

ctx.GasMeter().ConsumeGas(evmResp.GasUsed, "deploy erc20 funtoken contract")

Expand Down
5 changes: 3 additions & 2 deletions x/evm/keeper/funtoken_from_erc20.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ func (k *Keeper) createFunTokenFromERC20(
if stateDB == nil {
stateDB = k.NewStateDB(ctx, statedb.NewEmptyTxConfig(gethcommon.BytesToHash(ctx.HeaderHash())))
}
defer func() {
k.Bank.StateDB = nil
}()
evmMsg := gethcore.NewMessage(
evm.EVM_MODULE_ADDRESS,
&erc20,
Expand Down Expand Up @@ -184,8 +187,6 @@ func (k *Keeper) createFunTokenFromERC20(
if err != nil {
return nil, errors.Wrap(err, "failed to commit stateDB")
}
// Don't need the StateDB anymore because it's not usable after committing
k.Bank.StateDB = nil

return funtoken, k.FunTokens.SafeInsert(
ctx, erc20, bankDenom, false,
Expand Down
17 changes: 11 additions & 6 deletions x/evm/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ func (k *Keeper) EthereumTx(
if stateDB == nil {
stateDB = k.NewStateDB(ctx, txConfig)
}
defer func() {
k.Bank.StateDB = nil
}()
evmObj := k.NewEVM(ctx, evmMsg, evmCfg, nil /*tracer*/, stateDB)
evmResp, err = k.ApplyEvmMsg(ctx, evmMsg, evmObj, nil /*tracer*/, true /*commit*/, txConfig.TxHash, false /*fullRefundLeftoverGas*/)
if err != nil {
Expand Down Expand Up @@ -341,8 +344,6 @@ func (k *Keeper) ApplyEvmMsg(
if err := evmObj.StateDB.(*statedb.StateDB).Commit(); err != nil {
return nil, errors.Wrap(err, "ApplyEvmMsg: failed to commit stateDB")
}
// after we commit, the StateDB is no longer usable so we discard it and let the Golang garbage collector dispose of it
k.Bank.StateDB = nil
}
// Rare case of uint64 gas overflow
if msg.Gas() < leftoverGas {
Expand Down Expand Up @@ -544,10 +545,13 @@ func (k Keeper) convertCoinToEvmBornCoin(
true,
)
txConfig := k.TxConfig(ctx, gethcommon.Hash{})
var stateDB *statedb.StateDB = k.Bank.StateDB
stateDB := k.Bank.StateDB
if stateDB == nil {
stateDB = k.NewStateDB(ctx, txConfig)
}
defer func() {
k.Bank.StateDB = nil
}()
evmObj := k.NewEVM(ctx, evmMsg, k.GetEVMConfig(ctx), nil /*tracer*/, stateDB)
evmResp, err := k.CallContractWithInput(
ctx,
Expand All @@ -572,7 +576,6 @@ func (k Keeper) convertCoinToEvmBornCoin(
if err != nil {
return nil, errors.Wrap(err, "failed to commit stateDB")
}
k.Bank.StateDB = nil

_ = ctx.EventManager().EmitTypedEvent(&evm.EventConvertCoinToEvm{
Sender: sender.String(),
Expand All @@ -596,10 +599,13 @@ func (k Keeper) convertCoinToEvmBornERC20(
funTokenMapping evm.FunToken,
) (*evm.MsgConvertCoinToEvmResponse, error) {
// needs to run first to populate the StateDB on the BankKeeperExtension
var stateDB *statedb.StateDB = k.Bank.StateDB
stateDB := k.Bank.StateDB
if stateDB == nil {
stateDB = k.NewStateDB(ctx, k.TxConfig(ctx, gethcommon.Hash{}))
}
defer func() {
k.Bank.StateDB = nil
}()

erc20Addr := funTokenMapping.Erc20Addr.Address
// 1 | Caller transfers Bank Coins to be converted to ERC20 tokens.
Expand Down Expand Up @@ -664,7 +670,6 @@ func (k Keeper) convertCoinToEvmBornERC20(
if err := stateDB.Commit(); err != nil {
return nil, errors.Wrap(err, "failed to commit stateDB")
}
k.Bank.StateDB = nil

// Emit event with the actual amount received
_ = ctx.EventManager().EmitTypedEvent(&evm.EventConvertCoinToEvm{
Expand Down
1 change: 0 additions & 1 deletion x/evm/precompile/funtoken.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ func (p precompileFunToken) Run(
if err != nil {
return nil, err
}
p.evmKeeper.Bank.StateDB = startResult.StateDB

// Gracefully handles "out of gas"
defer HandleOutOfGasPanic(&err)()
Expand Down
5 changes: 0 additions & 5 deletions x/evm/precompile/wasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ func (p precompileWasm) Run(

abciEventsStartIdx := len(startResult.CacheCtx.EventManager().Events())

// NOTE: The NibiruBankKeeper needs to reference the current [vm.StateDB] before
// any operation that has the potential to use Bank send methods. This will
// guarantee that [evmkeeper.Keeper.SetAccBalance] journal changes are
// recorded if wei (NIBI) is transferred.
p.Bank.StateDB = startResult.StateDB
switch PrecompileMethod(startResult.Method.Name) {
case WasmMethod_execute:
bz, err = p.execute(startResult, contract.CallerAddress, readonly)
Expand Down
Loading