CosmWasm/wasmd

design: Why does consumeGas panic & not return an error?

Reecepbcups opened this issue · 0 comments

func (k Keeper) consumeRuntimeGas(ctx sdk.Context, gas uint64) panics in function calls such as Sudo calls even though an error for this function is thrown

For developers, this is unexpected behavior, especially when using a childCtx with a gas limit, expecting an error to be thrown.

It then required work around like the following from Juno with a recover()

// Execute contract, recover from panic
func ExecuteContract(k wasmtypes.ContractOpsKeeper, childCtx sdk.Context, contractAddr sdk.AccAddress, msgBz []byte, err *error) {
	// Recover from panic, return error
	defer func() {
		if recoveryError := recover(); recoveryError != nil {
			// Determine error associated with panic
			if isOutofGas, msg := IsOutOfGasError(recoveryError); isOutofGas {
				*err = ErrOutOfGas.Wrapf("%s", msg)
			} else {
				*err = ErrContractExecutionPanic.Wrapf("%s", recoveryError)
			}
		}
	}()

	// Execute contract with sudo
	_, *err = k.Sudo(childCtx, contractAddr, msgBz)
}

// Check if error is out of gas error
func IsOutOfGasError(err any) (bool, string) {
	switch e := err.(type) {
	case storetypes.ErrorOutOfGas:
		return true, e.Descriptor
	case storetypes.ErrorGasOverflow:
		return true, e.Descriptor
	default:
		return false, ""
	}
}

This just seems wrong given Sudo already returns an error, so persist a Gas error up?