From 9d9b14b95299b793c1a0f4cb8f42e4e0252fed1c Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Fri, 25 Mar 2022 17:40:45 -0400 Subject: [PATCH] More robust JSON-RPC error handling for reverted executions (#2603). --- .../providers/src.ts/json-rpc-provider.ts | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/providers/src.ts/json-rpc-provider.ts b/packages/providers/src.ts/json-rpc-provider.ts index 6caab70524..dbacc3a828 100644 --- a/packages/providers/src.ts/json-rpc-provider.ts +++ b/packages/providers/src.ts/json-rpc-provider.ts @@ -22,20 +22,48 @@ import { BaseProvider, Event } from "./base-provider"; const errorGas = [ "call", "estimateGas" ]; +function spelunk(value: any): null | { message: string, data: string } { + if (value == null) { return null; } + + // These *are* the droids we're looking for. + if (typeof(value.message) === "string" && value.message.match("reverted") && isHexString(value.data)) { + return { message: value.message, data: value.data }; + } + + // Spelunk further... + if (typeof(value) === "object") { + for (const key in value) { + const result = spelunk(value[key]); + if (result) { return result; } + } + return null; + } + + // Might be a JSON string we can further descend... + if (typeof(value) === "string") { + try { + return spelunk(JSON.parse(value)); + } catch (error) { } + } + + return null; +} + function checkError(method: string, error: any, params: any): any { + // Undo the "convenience" some nodes are attempting to prevent backwards // incompatibility; maybe for v6 consider forwarding reverts as errors - if (method === "call" && error.code === Logger.errors.SERVER_ERROR) { - const e = error.error; - if (e && e.message.match("reverted") && isHexString(e.data)) { - return e.data; - } + if (method === "call") { + const result = spelunk(error); + if (result) { return result.data; } logger.throwError("missing revert data in call exception", Logger.errors.CALL_EXCEPTION, { error, data: "0x" }); } + // @TODO: Should we spelunk for message too? + let message = error.message; if (error.code === Logger.errors.SERVER_ERROR && error.error && typeof(error.error.message) === "string") { message = error.error.message;