diff --git a/src/ethers.ts b/src/ethers.ts index 5a22461..c8f3dbb 100644 --- a/src/ethers.ts +++ b/src/ethers.ts @@ -137,8 +137,18 @@ export class EthersMulticall { const signature = FunctionFragment.from(fragment).format(); const callIdentifier = [contract.address, signature].join(":"); - if (!res.success) throw Error(`${callIdentifier} call revert exception`); - if (res.returnData === "0x") throw Error(`${callIdentifier} empty return data exception`); + if (!res.success) + return { + error: Error(`${callIdentifier} call revert exception`), + address: contract.address, + params: params.slice(0, fragment.inputs.length), + }; + if (res.returnData === "0x") + return { + error: Error(`${callIdentifier} empty return data exception`), + address: contract.address, + params: params.slice(0, fragment.inputs.length), + }; try { const result = new Interface([]).decodeFunctionResult(fragment, res.returnData); diff --git a/test/index.spec.ts b/test/index.spec.ts index d65c938..b34f6a1 100644 --- a/test/index.spec.ts +++ b/test/index.spec.ts @@ -83,6 +83,25 @@ describe("ethers-multicall", () => { ]); }); + it("should gracefully fail in a Promise.all when batching queries where one query reverts", async () => { + const multicall = new EthersMulticall(rpcProvider); + const wrappedUni = multicall.wrap(uni); + const wrappedUnknown = multicall.wrap( + new ethers.Contract("0xd6409e50c05879c5B9E091EB01E9Dd776d00A151", UniAbi, signer) + ); + + expect(Promise.all([wrappedUni.symbol(), wrappedUnknown.symbol()])).resolves.toEqual([ + "UNI", + { + address: "0xd6409e50c05879c5B9E091EB01E9Dd776d00A151", + error: new Error( + "0xd6409e50c05879c5B9E091EB01E9Dd776d00A151:symbol() empty return data exception" + ), + params: [], + }, + ]); + }); + it("should batch UNI calls without Promise.all", async () => { const multicall = new EthersMulticall(rpcProvider); const wrappedUni = multicall.wrap(uni);