Skip to content

Commit 2c3dae0

Browse files
committedMay 12, 2022
Ensure gas estimate errors are not call exceptions in disguise (#2954).

File tree

1 file changed

+26
-9
lines changed

1 file changed

+26
-9
lines changed
 

‎packages/providers/src.ts/json-rpc-provider.ts

+26-9
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,21 @@ import { BaseProvider, Event } from "./base-provider";
2222

2323
const errorGas = [ "call", "estimateGas" ];
2424

25-
function spelunk(value: any): null | { message: string, data: string } {
25+
function spelunk(value: any, requireData: boolean): null | { message: string, data: null | string } {
2626
if (value == null) { return null; }
2727

2828
// These *are* the droids we're looking for.
29-
if (typeof(value.message) === "string" && value.message.match("reverted") && isHexString(value.data)) {
30-
return { message: value.message, data: value.data };
29+
if (typeof(value.message) === "string" && value.message.match("reverted")) {
30+
const data = isHexString(value.data) ? value.data: null;
31+
if (!requireData || data) {
32+
return { message: value.message, data };
33+
}
3134
}
3235

3336
// Spelunk further...
3437
if (typeof(value) === "object") {
3538
for (const key in value) {
36-
const result = spelunk(value[key]);
39+
const result = spelunk(value[key], requireData);
3740
if (result) { return result; }
3841
}
3942
return null;
@@ -42,7 +45,7 @@ function spelunk(value: any): null | { message: string, data: string } {
4245
// Might be a JSON string we can further descend...
4346
if (typeof(value) === "string") {
4447
try {
45-
return spelunk(JSON.parse(value));
48+
return spelunk(JSON.parse(value), requireData);
4649
} catch (error) { }
4750
}
4851

@@ -51,17 +54,33 @@ function spelunk(value: any): null | { message: string, data: string } {
5154

5255
function checkError(method: string, error: any, params: any): any {
5356

57+
const transaction = params.transaction || params.signedTransaction;
58+
5459
// Undo the "convenience" some nodes are attempting to prevent backwards
5560
// incompatibility; maybe for v6 consider forwarding reverts as errors
5661
if (method === "call") {
57-
const result = spelunk(error);
62+
const result = spelunk(error, true);
5863
if (result) { return result.data; }
5964

65+
// Nothing descriptive..
6066
logger.throwError("missing revert data in call exception; Transaction reverted without a reason string", Logger.errors.CALL_EXCEPTION, {
61-
error, data: "0x"
67+
data: "0x", transaction, error
6268
});
6369
}
6470

71+
if (method === "estimateGas") {
72+
// Try to find something, with a preference on SERVER_ERROR body
73+
let result = spelunk(error.body, false);
74+
if (result == null) { result = spelunk(error, false); }
75+
76+
// Found "reverted", this is a CALL_EXCEPTION
77+
if (result) {
78+
logger.throwError("cannot estimate gas; transaction may fail or may require manual gas limit", Logger.errors.UNPREDICTABLE_GAS_LIMIT, {
79+
reason: result.message, method, transaction, error
80+
});
81+
}
82+
}
83+
6584
// @TODO: Should we spelunk for message too?
6685

6786
let message = error.message;
@@ -74,8 +93,6 @@ function checkError(method: string, error: any, params: any): any {
7493
}
7594
message = (message || "").toLowerCase();
7695

77-
const transaction = params.transaction || params.signedTransaction;
78-
7996
// "insufficient funds for gas * price + value + cost(data)"
8097
if (message.match(/insufficient funds|base fee exceeds gas limit/i)) {
8198
logger.throwError("insufficient funds for intrinsic transaction cost", Logger.errors.INSUFFICIENT_FUNDS, {

0 commit comments

Comments
 (0)
Please sign in to comment.