diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 4484266bf5b4..e2c384ba23e6 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1433,15 +1433,11 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr result, err := DoCall(ctx, b, args, blockNrOrHash, nil, vm.Config{}, 0, gasCap) if err != nil { if errors.Is(err, vm.ErrOutOfGas) || errors.Is(err, core.ErrIntrinsicGas) { - return false, nil, nil // Special case, raise gas limit + return true, nil, nil // Special case, raise gas limit } - return false, nil, err // Bail out + return true, nil, err // Bail out } - if result.Failed() { - return false, result, nil - } - - return true, nil, nil + return result.Failed(), result, nil } // If the transaction is a plain value transfer, short circuit estimation and @@ -1460,7 +1456,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr // Execute the binary search and hone in on an executable gas limit for lo+1 < hi { mid := (hi + lo) / 2 - ok, _, err := executable(mid) + failed, _, err := executable(mid) // If the error is not nil(consensus error), it means the provided message // call or transaction will never be accepted no matter how much gas it is @@ -1469,7 +1465,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr return 0, err } - if !ok { + if failed { lo = mid } else { hi = mid @@ -1478,21 +1474,30 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr // Reject the transaction as invalid if it still fails at the highest allowance if hi == cap { - ok, res, err := executable(hi) + failed, result, err := executable(hi) if err != nil { return 0, err } - if !ok { - if res.Err != vm.ErrOutOfGas { - if len(res.ReturnData) > 0 { - return 0, newRevertError(res.ReturnData) + if failed { + if result != nil && result.Err != vm.ErrOutOfGas { + var revert string + if len(result.Revert()) > 0 { + ret, err := abi.UnpackRevert(result.Revert()) + if err != nil { + revert = hexutil.Encode(result.Revert()) + } else { + revert = ret + } + } + return 0, estimateGasError{ + error: "always failing transaction", + vmerr: result.Err, + revert: revert, } - return 0, res.Err } - // Otherwise, the specified gas cap is too low - return 0, fmt.Errorf("gas required exceeds allowance (%d)", cap) + return 0, estimateGasError{error: fmt.Sprintf("gas required exceeds allowance (%d)", cap)} } } return hexutil.Uint64(hi), nil