@@ -22,18 +22,21 @@ import { BaseProvider, Event } from "./base-provider";
22
22
23
23
const errorGas = [ "call" , "estimateGas" ] ;
24
24
25
- function spelunk ( value : any ) : null | { message : string , data : string } {
25
+ function spelunk ( value : any , requireData : boolean ) : null | { message : string , data : null | string } {
26
26
if ( value == null ) { return null ; }
27
27
28
28
// 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
+ }
31
34
}
32
35
33
36
// Spelunk further...
34
37
if ( typeof ( value ) === "object" ) {
35
38
for ( const key in value ) {
36
- const result = spelunk ( value [ key ] ) ;
39
+ const result = spelunk ( value [ key ] , requireData ) ;
37
40
if ( result ) { return result ; }
38
41
}
39
42
return null ;
@@ -42,7 +45,7 @@ function spelunk(value: any): null | { message: string, data: string } {
42
45
// Might be a JSON string we can further descend...
43
46
if ( typeof ( value ) === "string" ) {
44
47
try {
45
- return spelunk ( JSON . parse ( value ) ) ;
48
+ return spelunk ( JSON . parse ( value ) , requireData ) ;
46
49
} catch ( error ) { }
47
50
}
48
51
@@ -51,17 +54,33 @@ function spelunk(value: any): null | { message: string, data: string } {
51
54
52
55
function checkError ( method : string , error : any , params : any ) : any {
53
56
57
+ const transaction = params . transaction || params . signedTransaction ;
58
+
54
59
// Undo the "convenience" some nodes are attempting to prevent backwards
55
60
// incompatibility; maybe for v6 consider forwarding reverts as errors
56
61
if ( method === "call" ) {
57
- const result = spelunk ( error ) ;
62
+ const result = spelunk ( error , true ) ;
58
63
if ( result ) { return result . data ; }
59
64
65
+ // Nothing descriptive..
60
66
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
62
68
} ) ;
63
69
}
64
70
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
+
65
84
// @TODO : Should we spelunk for message too?
66
85
67
86
let message = error . message ;
@@ -74,8 +93,6 @@ function checkError(method: string, error: any, params: any): any {
74
93
}
75
94
message = ( message || "" ) . toLowerCase ( ) ;
76
95
77
- const transaction = params . transaction || params . signedTransaction ;
78
-
79
96
// "insufficient funds for gas * price + value + cost(data)"
80
97
if ( message . match ( / i n s u f f i c i e n t f u n d s | b a s e f e e e x c e e d s g a s l i m i t / i) ) {
81
98
logger . throwError ( "insufficient funds for intrinsic transaction cost" , Logger . errors . INSUFFICIENT_FUNDS , {
0 commit comments