Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit 7a18c7e

Browse files
authored
Nikos/5931/coverage web3 abi (#5934)
* Fix type in Events test * Add data and tests for encodeErrorSignature * Decode contract errors test * Delete unused function * Add invalid data for decode contract erros * Add tuple in data * isAbiCostructor * Update changelog
1 parent 5e469af commit 7a18c7e

File tree

8 files changed

+243
-30
lines changed

8 files changed

+243
-30
lines changed

packages/web3-eth-abi/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8989
- `decodeErrorData` from `web3-eth-contract` is now exported from this package and was renamed to `decodeContractErrorData` (#5844)
9090

9191
## [Unreleased]
92+
93+
### Removed
94+
95+
- Removed `formatDecodedObject` function (#5934)

packages/web3-eth-abi/src/api/parameters_api.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,6 @@ import { HexString, AbiInput, DecodedParams } from 'web3-types';
2121
import ethersAbiCoder from '../ethers_abi_coder';
2222
import { formatParam, isAbiFragment, mapTypes, modifyParams } from '../utils';
2323

24-
/**
25-
* Helper function to format the decoded object
26-
*/
27-
const formatDecodedObject = (
28-
abi: { [key: string]: unknown },
29-
input: { [key: string]: unknown },
30-
): { [key: string]: unknown } => {
31-
let index = 0;
32-
const res: { [key: string]: unknown } = {};
33-
for (const j of Object.keys(abi)) {
34-
if (typeof abi[j] === 'string') {
35-
res[j] = input[j];
36-
res[index] = input[j];
37-
}
38-
if (typeof abi[j] === 'object') {
39-
res[j] = formatDecodedObject(
40-
abi[j] as { [key: string]: unknown },
41-
input[j] as { [key: string]: unknown },
42-
);
43-
res[index] = res[j];
44-
}
45-
index += 1;
46-
}
47-
48-
return res;
49-
};
50-
5124
/**
5225
* Encodes a parameter based on its type to its ABI representation.
5326
* @param abi - An array of {@link AbiInput}. See [Solidity's documentation](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html#json) for more details.

packages/web3-eth-abi/test/fixtures/data.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,35 @@ export const invalidEventsSignatures: { input: any; output: string }[] = [
289289
{ input: undefined, output: 'Invalid parameter value in encodeEventSignature' },
290290
];
291291

292+
export const validErrorsSignatures: { input: any; output: string }[] = [
293+
{
294+
input: 'Unauthorized()',
295+
output: '0x82b4290015f7ec7256ca2a6247d3c2a89c4865c0e791456df195f40ad0a81367',
296+
},
297+
{
298+
input: {
299+
inputs: [{ internalType: 'string', name: '', type: 'string' }],
300+
name: 'CustomError',
301+
type: 'error',
302+
},
303+
output: '0x8d6ea8bed4afafaebcad40e72174583b8bf4969c5d3bc84536051f3939bf9d81',
304+
},
305+
{
306+
input: 'Error(string)',
307+
output: '0x08c379a0afcc32b1a39302f7cb8073359698411ab5fd6e3edb2c02c0b5fba8aa',
308+
},
309+
];
310+
311+
export const invalidErrorSignatures: { input: any; output: string }[] = [
312+
{ input: 345, output: 'Invalid parameter value in encodeErrorSignature' },
313+
{ input: {}, output: 'Invalid parameter value in encodeErrorSignature' },
314+
{ input: ['mystring'], output: 'Invalid parameter value in encodeErrorSignature' },
315+
// Using "null" value intentionally for validation
316+
// eslint-disable-next-line no-null/no-null
317+
{ input: null, output: 'Invalid parameter value in encodeErrorSignature' },
318+
{ input: undefined, output: 'Invalid parameter value in encodeErrorSignature' },
319+
];
320+
292321
export const validDecodeLogsData: {
293322
input: { abi: any; data: any; topics: any };
294323
output: Record<string, unknown>;
@@ -677,6 +706,13 @@ export const validEncodeParametersData: {
677706
],
678707
output: '0x00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000000000000000000000000000000002d000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000ff',
679708
},
709+
{
710+
input: [
711+
['uint', 'tuple(uint256, string)'],
712+
[1234, [5678, 'Hello World']],
713+
],
714+
output: '0x00000000000000000000000000000000000000000000000000000000000004d20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000162e0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000b48656c6c6f20576f726c64000000000000000000000000000000000000000000',
715+
},
680716
];
681717

682718
export const inValidEncodeParametersData: {
@@ -900,3 +936,77 @@ export const inValidDecodeParametersData: {
900936
output: 'Parameter decoding error',
901937
},
902938
];
939+
940+
export const validDecodeContractErrorData: {
941+
input: any[];
942+
output: any;
943+
}[] = [
944+
{
945+
input: [
946+
[
947+
{ inputs: [], name: 'ErrorWithNoParams', type: 'error' },
948+
{
949+
inputs: [
950+
{ name: 'code', type: 'uint256' },
951+
{ name: 'message', type: 'string' },
952+
],
953+
name: 'ErrorWithParams',
954+
type: 'error',
955+
},
956+
],
957+
{
958+
code: 12,
959+
message: 'message',
960+
data: '0xc85bda60000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000',
961+
},
962+
],
963+
output: {
964+
errorName: 'ErrorWithParams',
965+
errorSignature: 'ErrorWithParams(uint256,string)',
966+
errorArgs: {
967+
code: 42,
968+
message: 'This is an error with params',
969+
},
970+
},
971+
},
972+
];
973+
974+
export const invalidDecodeContractErrorData: {
975+
input: any[];
976+
}[] = [
977+
{
978+
input: [
979+
[
980+
{ inputs: [], name: 'ErrorWithNoParams', type: 'error' },
981+
{
982+
inputs: [
983+
{ name: 'code', type: 'uint256' },
984+
{ name: 'message', type: 'string' },
985+
],
986+
name: 'ErrorWithParams',
987+
type: 'error',
988+
},
989+
],
990+
{
991+
code: 12,
992+
message: 'message',
993+
data: '0xc85bda60000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000123450000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c5468697320697320616e206572726f72207769746820706172616d7300000000',
994+
},
995+
],
996+
},
997+
];
998+
999+
export const validIsAbiConstructorFragment: {
1000+
input: any;
1001+
}[] = [
1002+
{
1003+
input: { inputs: [], stateMutability: 'nonpayable', type: 'constructor' },
1004+
},
1005+
];
1006+
export const invalidIsAbiConstructorFragment: {
1007+
input: any;
1008+
}[] = [
1009+
{
1010+
input: { inputs: [], stateMutability: 'nonpayable', type: 'function' },
1011+
},
1012+
];
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
This file is part of web3.js.
3+
4+
web3.js is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
web3.js is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License
15+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
import { encodeErrorSignature } from '../../../src/api/errors_api';
19+
import { validErrorsSignatures, invalidErrorSignatures } from '../../fixtures/data';
20+
21+
describe('errors_api', () => {
22+
describe('encodeErrorSignature', () => {
23+
describe('valid data', () => {
24+
it.each(validErrorsSignatures)(
25+
'should pass for valid values: %s',
26+
({ input, output }) => {
27+
expect(encodeErrorSignature(input)).toEqual(output);
28+
},
29+
);
30+
});
31+
32+
describe('invalid data', () => {
33+
it.each(invalidErrorSignatures)(
34+
'should pass for valid values: %s',
35+
({ input, output }) => {
36+
expect(() => encodeErrorSignature(input)).toThrow(output);
37+
},
38+
);
39+
});
40+
});
41+
});

packages/web3-eth-abi/test/unit/api/events_api.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ describe('events_api', () => {
3030
});
3131
describe('invalid data', () => {
3232
it.each(invalidEventsSignatures)(
33-
'should pass for valid values: %s',
33+
'should fail for invalid values: %s',
3434
({ input, output }) => {
3535
expect(() => encodeEventSignature(input)).toThrow(output);
3636
},
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
This file is part of web3.js.
3+
4+
web3.js is free software: you can redistribute it and/or modify
5+
it under the terms of the GNU Lesser General Public License as published by
6+
the Free Software Foundation, either version 3 of the License, or
7+
(at your option) any later version.
8+
9+
web3.js is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public License
15+
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
import { Eip838ExecutionError } from 'web3-errors';
19+
import { decodeContractErrorData } from '../../src/decode_contract_error_data';
20+
21+
import { validDecodeContractErrorData, invalidDecodeContractErrorData } from '../fixtures/data';
22+
23+
describe('decodeContractErrorData', () => {
24+
describe('valid data', () => {
25+
it.each(validDecodeContractErrorData)(
26+
'%#: should pass for valid values: %j',
27+
({ input: [abi, errorData], output }) => {
28+
const err = new Eip838ExecutionError(
29+
errorData.code,
30+
errorData.message,
31+
errorData.data,
32+
);
33+
34+
decodeContractErrorData(abi, err);
35+
36+
expect(err.errorName).toEqual(output.errorName);
37+
expect(err.errorSignature).toEqual(output.errorSignature);
38+
expect(err.errorArgs?.message).toEqual(output.errorArgs?.message);
39+
expect(Number(err.errorArgs?.code)).toEqual(output.errorArgs?.code);
40+
},
41+
);
42+
});
43+
44+
describe('invalid data', () => {
45+
it.each(invalidDecodeContractErrorData)(
46+
'%#: should throw for invalid values: %j',
47+
({ input: [abi, errorData] }) => {
48+
// mock console.error
49+
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => 'error');
50+
const err = new Eip838ExecutionError(
51+
errorData.code,
52+
errorData.message,
53+
errorData.data,
54+
);
55+
decodeContractErrorData(abi, err);
56+
expect(consoleSpy).toHaveBeenCalled();
57+
},
58+
);
59+
});
60+
});

packages/web3-eth-abi/test/unit/utils.test.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,13 @@ You should have received a copy of the GNU Lesser General Public License
1515
along with web3.js. If not, see <http://www.gnu.org/licenses/>.
1616
*/
1717

18-
import { jsonInterfaceMethodToString } from '../../src/utils';
19-
import { jsonInterfaceInvalidData, jsonInterfaceValidData } from '../fixtures/data';
18+
import { jsonInterfaceMethodToString, isAbiConstructorFragment } from '../../src/utils';
19+
import {
20+
jsonInterfaceInvalidData,
21+
jsonInterfaceValidData,
22+
validIsAbiConstructorFragment,
23+
invalidIsAbiConstructorFragment,
24+
} from '../fixtures/data';
2025

2126
describe('utils', () => {
2227
describe('jsonInterfaceMethodToString', () => {
@@ -42,4 +47,17 @@ describe('utils', () => {
4247
});
4348
});
4449
});
50+
describe('isAbiConstructorFragment', () => {
51+
describe('valid cases', () => {
52+
it.each(validIsAbiConstructorFragment)('%s', ({ input }) => {
53+
expect(isAbiConstructorFragment(input)).toBeTruthy();
54+
});
55+
});
56+
57+
describe('invalid cases', () => {
58+
it.each(invalidIsAbiConstructorFragment)('%s', ({ input }) => {
59+
expect(isAbiConstructorFragment(input)).toBeFalsy();
60+
});
61+
});
62+
});
4563
});

packages/web3/test/shared_fixtures/data.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,11 @@ export const validEncodeParametersData: {
2727
],
2828
output: '0x000000000000000000000000000000000000000000000000000000008bd02b7b0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000748656c6c6f212500000000000000000000000000000000000000000000000000',
2929
},
30+
{
31+
input: [
32+
['uint', 'tuple(uint256, string)'],
33+
[1234, [5678, 'Hello World']],
34+
],
35+
output: '',
36+
},
3037
];

0 commit comments

Comments
 (0)