diff --git a/cosmos/x/evm/plugins/precompile/plugin.go b/cosmos/x/evm/plugins/precompile/plugin.go index a625f546e..a95e1b464 100644 --- a/cosmos/x/evm/plugins/precompile/plugin.go +++ b/cosmos/x/evm/plugins/precompile/plugin.go @@ -157,7 +157,7 @@ func (p *plugin) Run( defer p.enableReentrancy(sdb) // recover from any WriteProtection or OutOfGas panic for the EVM to handle as a vm error - defer RecoveryHandler(&err) + defer RecoveryHandler(ctx, &err) // use a precompile-specific gas meter for dynamic consumption gm := storetypes.NewGasMeter(suppliedGas) diff --git a/cosmos/x/evm/plugins/precompile/plugin_test.go b/cosmos/x/evm/plugins/precompile/plugin_test.go index f351f8f7a..0c444e6d9 100644 --- a/cosmos/x/evm/plugins/precompile/plugin_test.go +++ b/cosmos/x/evm/plugins/precompile/plugin_test.go @@ -104,12 +104,10 @@ var _ = Describe("plugin", func() { }) It("should catch panics and propagate", func() { - Expect(func() { - _, _, _ = p.Run(e, &mockPanicking{ - err: errors.New("error"), - }, []byte{}, addr, new(big.Int), 30, false) - }, - ).To(Panic()) + _, _, vmErr := p.Run(e, &mockPanicking{ + err: errors.New("error"), + }, []byte{}, addr, new(big.Int), 30, false) + Expect(errors.Is(vmErr, vm.ErrExecutionReverted)).To(BeTrue()) }) }) diff --git a/cosmos/x/evm/plugins/precompile/recovery.go b/cosmos/x/evm/plugins/precompile/recovery.go index ace605fdd..f03e661aa 100644 --- a/cosmos/x/evm/plugins/precompile/recovery.go +++ b/cosmos/x/evm/plugins/precompile/recovery.go @@ -27,12 +27,14 @@ import ( "github.com/berachain/polaris/eth/core/vm" "github.com/berachain/polaris/lib/utils" + + sdk "github.com/cosmos/cosmos-sdk/types" ) // RecoveryHandler is used to recover from any WriteProtection and gas consumption panics that // occur during precompile execution; the handler modifies the given error to be returned to the // caller. Any other type of panic is propogated up to the caller via panic. -func RecoveryHandler(err *error) { +func RecoveryHandler(ctx sdk.Context, vmErr *error) { if panicked := recover(); panicked != nil { // NOTE: this only propagates an error back to the EVM if the type of the given panic // is ErrWriteProtection, Cosmos ErrorOutOfGas, Cosmos ErrorGasOverflow, or Cosmos @@ -40,16 +42,21 @@ func RecoveryHandler(err *error) { switch { case utils.Implements[error](panicked) && errors.Is(utils.MustGetAs[error](panicked), vm.ErrWriteProtection): - *err = vm.ErrWriteProtection + *vmErr = vm.ErrWriteProtection case utils.Implements[storetypes.ErrorGasOverflow](panicked): fallthrough case utils.Implements[storetypes.ErrorOutOfGas](panicked): fallthrough case utils.Implements[storetypes.ErrorNegativeGasConsumed](panicked): - *err = vm.ErrOutOfGas + *vmErr = vm.ErrOutOfGas + case utils.Implements[error](panicked): + // any other type of panic value is returned as a vm error: execution reverted + // NOTE: precompile txs which panic will be included in the block as failed txs + ctx.Logger().Error("panic recovered in precompile execution", "err", panicked) + *vmErr = errors.Join(vm.ErrExecutionReverted, utils.MustGetAs[error](panicked)) default: - // any other type of panic value is ignored and passed up the call stack - panic(panicked) + ctx.Logger().Error("panic recovered in precompile execution", "panic", panicked) + *vmErr = vm.ErrExecutionReverted } } }