Skip to content

Commit

Permalink
handle multicall revert
Browse files Browse the repository at this point in the history
  • Loading branch information
bergeron committed Dec 19, 2024
1 parent 3078318 commit 325029b
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 3 deletions.
46 changes: 46 additions & 0 deletions packages/assets-controllers/src/multicall.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,50 @@ describe('multicall', () => {
]);
});
});

describe('error handling of reverts', () => {
const call = {
contract: new Contract(
'0x0000000000000000000000000000000000000001',
abiERC20,
provider,
),
functionSignature: 'balanceOf(address)',
arguments: ['0x0000000000000000000000000000000000000000'],
};

it('should fall back to parallel calls when multicall reverts', async () => {
jest.spyOn(provider, 'call').mockImplementationOnce(() => {
const error = { code: 'CALL_EXCEPTION' };
return Promise.reject(error);
});

jest
.spyOn(provider, 'call')
.mockImplementationOnce(() =>
Promise.resolve(defaultAbiCoder.encode(['uint256'], [1])),
);

const results = await multicallOrFallback([call], '0x1', provider);

expect(results).toMatchObject([
{
success: true,
// eslint-disable-next-line @typescript-eslint/naming-convention
value: { _hex: '0x01' },
},
]);
});

it('should throw rpc errors other than revert', async () => {
const error = { code: 'network error' };
jest.spyOn(provider, 'call').mockImplementationOnce(() => {
return Promise.reject(error);
});

await expect(
multicallOrFallback([call], '0x1', provider),
).rejects.toMatchObject(error);
});
});
});
26 changes: 23 additions & 3 deletions packages/assets-controllers/src/multicall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,27 @@ export const multicallOrFallback = async (
}

const multicallAddress = MULTICALL_CONTRACT_BY_CHAINID[chainId];
return await (multicallAddress
? multicall(calls, multicallAddress, provider, maxCallsPerMulticall)
: fallback(calls, maxCallsParallel));
if (multicallAddress) {
try {
return await multicall(
calls,
multicallAddress,
provider,
maxCallsPerMulticall,
);
} catch (error: unknown) {
// Fallback only on revert
// https://docs.ethers.org/v5/troubleshooting/errors/#help-CALL_EXCEPTION
if (
!error ||
typeof error !== 'object' ||
!('code' in error) ||
error.code !== 'CALL_EXCEPTION'
) {
throw error;
}
}
}

return await fallback(calls, maxCallsParallel);
};

0 comments on commit 325029b

Please sign in to comment.