Skip to content
This repository has been archived by the owner on Apr 25, 2023. It is now read-only.

Commit

Permalink
fix(stack-trace): improve error stack trace
Browse files Browse the repository at this point in the history
  • Loading branch information
Rubilmax committed Sep 6, 2022
1 parent 106a2b2 commit dc5d43c
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 12 deletions.
5 changes: 1 addition & 4 deletions src/contract.ts
Expand Up @@ -5,7 +5,6 @@ import { ContractCall } from "./ethers";
export class MulticallContract {
private _address: string;
private _abi: Fragment[];
private _stack?: string;
private _functions: FunctionFragment[];

get address() {
Expand All @@ -24,9 +23,8 @@ export class MulticallContract {
return this._functions;
}

constructor(address: string, abi: JsonFragment[] | string[] | Fragment[], stack?: string) {
constructor(address: string, abi: JsonFragment[] | string[] | Fragment[]) {
this._address = address;
this._stack = stack;

this._abi = abi.map((item: JsonFragment | string | Fragment) => Fragment.from(item));
this._functions = this._abi
Expand All @@ -41,7 +39,6 @@ export class MulticallContract {
fragment: frag,
address,
params,
stack,
});

if (!this[frag.name])
Expand Down
16 changes: 9 additions & 7 deletions src/ethers.ts
Expand Up @@ -119,13 +119,14 @@ export class EthersMulticall implements IMulticallWrapper {
try {
const outputs = call.fragment.outputs!;
const result = new Interface([]).decodeFunctionResult(call.fragment, data);

return outputs.length === 1 ? result[0] : result;
} catch (err: any) {
const error = new Error(
`Multicall call failed for ${callIdentifier}: ${err.message} (decode)`
);
const error = new Error(`Multicall call failed for ${callIdentifier}: ${err.message}`);
error.name = error.message;
error.stack = call.stack;
return error;

throw error;
}
});

Expand All @@ -134,8 +135,7 @@ export class EthersMulticall implements IMulticallWrapper {

wrap<T extends TargetContract>(contract: T) {
const abi = contract.interface.fragments;
const stack = new Error().stack?.split("\n").slice(1).join("\n");
const multicallContract = new MulticallContract(contract.address, abi as any, stack);
const multicallContract = new MulticallContract(contract.address, abi as any);

const funcs = abi.reduce((memo, frag) => {
if (frag.type !== "function") return memo;
Expand All @@ -146,8 +146,10 @@ export class EthersMulticall implements IMulticallWrapper {
// Overwrite the function with a dataloader batched call
const multicallFunc = multicallContract[funcFrag.name].bind(multicallContract);
const newFunc = (...args: any) => {
const stack = new Error().stack?.split("\n").slice(1).join("\n");

const contractCall = multicallFunc(...args);
return this.dataLoader.load(contractCall);
return this.dataLoader.load({ ...contractCall, stack });
};

memo[funcFrag.name] = newFunc;
Expand Down
15 changes: 14 additions & 1 deletion test/index.spec.ts
Expand Up @@ -15,7 +15,7 @@ let rpcProvider: ethers.providers.JsonRpcProvider;
let _morpho: ethers.Contract;
let _uni: ethers.Contract;

describe("index", () => {
describe("ethers-multicall", () => {
beforeEach(() => {
rpcProvider = new ethers.providers.JsonRpcProvider(httpRpcUrl, 1);

Expand Down Expand Up @@ -151,5 +151,18 @@ describe("index", () => {

expect(totalSupplyBefore.toString()).toEqual(totalSupplyAfter.toString());
});

it("should throw a descriptive Error when querying unknown contract", async () => {
const multicall = new EthersMulticall(rpcProvider);
const wrappedUnknown = multicall.wrap(
new ethers.Contract("0xd6409e50c05879c5B9E091EB01E9Dd776d00A151", UniswapAbi)
);

expect(wrappedUnknown.symbol).rejects.toThrow(
new Error(
`Multicall call failed for 0xd6409e50c05879c5B9E091EB01E9Dd776d00A151:symbol(): call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ] (method="symbol()", data="0x", errorArgs=null, errorName=null, errorSignature=null, reason=null, code=CALL_EXCEPTION, version=abi/5.7.0)`
)
);
});
});
});

0 comments on commit dc5d43c

Please sign in to comment.