Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle common cases for smart contract errors according to EIP 838 #7155

30 changes: 30 additions & 0 deletions packages/web3-eth-abi/src/decode_contract_error_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,36 @@
errorSignature = jsonInterfaceMethodToString(errorAbi);
// decode abi.inputs according to EIP-838
errorArgs = decodeParameters([...errorAbi.inputs], error.data.substring(10));
} else if (error.data.startsWith('0x08c379a0')) {
// If ABI was not provided, check for the 2 famous errors: 'Error(string)' or 'Panic(uint256)'

errorName = 'Error';
errorSignature = 'Error(string)';
// decode abi.inputs according to EIP-838
errorArgs = decodeParameters(
[
{
name: 'message',
type: 'string',
},
],
error.data.substring(10),
);
} else if (error.data.startsWith('0x4e487b71')) {
errorName = 'Panic';
errorSignature = 'Panic(uint256)';
// decode abi.inputs according to EIP-838
errorArgs = decodeParameters(
[
{
name: 'code',
type: 'uint256',
},
],
error.data.substring(10),
);
} else {
console.error('No matching error abi found for error data', error.data);

Check warning on line 71 in packages/web3-eth-abi/src/decode_contract_error_data.ts

View check run for this annotation

Codecov / codecov/patch

packages/web3-eth-abi/src/decode_contract_error_data.ts#L70-L71

Added lines #L70 - L71 were not covered by tests
}
} catch (err) {
console.error(err);
Expand Down
34 changes: 34 additions & 0 deletions packages/web3-eth-abi/test/fixtures/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -974,6 +974,40 @@ export const validDecodeContractErrorData: {
input: any[];
output: any;
}[] = [
{
input: [
[],
{
code: 12,
message: 'message',
data: '0x08c379a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000155468697320697320612063616c6c207265766572740000000000000000000000',
},
],
output: {
errorName: 'Error',
errorSignature: 'Error(string)',
errorArgs: {
message: 'This is a call revert',
},
},
},
{
input: [
[],
{
code: 12,
message: 'message',
data: '0x4e487b71000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000',
},
],
output: {
errorName: 'Panic',
errorSignature: 'Panic(uint256)',
errorArgs: {
code: 42,
},
},
},
{
input: [
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ describe('decodeContractErrorData', () => {
expect(err.errorName).toEqual(output.errorName);
expect(err.errorSignature).toEqual(output.errorSignature);
expect(err.errorArgs?.message).toEqual(output.errorArgs?.message);
expect(Number(err.errorArgs?.code)).toEqual(output.errorArgs?.code);

// This ensures they are equal if one was provided
// It also skips if both are not provided
if (err.errorArgs?.code || output.errorArgs?.code) {
// eslint-disable-next-line jest/no-conditional-expect
expect(Number(err.errorArgs?.code)).toEqual(output.errorArgs?.code);
}
expect(err.cause?.code).toEqual(output.cause?.code);
},
);
Expand Down
Loading