Skip to content

Commit e13f7ed

Browse files
authored
Merge pull request #2173 from psychoplasma/custom-error-type-generation
Support for Generation of Custom Error type
2 parents e049b0b + 1320362 commit e13f7ed

File tree

11 files changed

+500
-0
lines changed

11 files changed

+500
-0
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
1515

1616
* bump snapshot version to 4.13.1 [#2160](https://github.com/hyperledger-web3j/web3j/pull/2160)
1717
* Upgrade to https://github.com/Consensys/tuweni/releases/tag/v2.7.0 [#2170](https://github.com/LFDT-web3j/web3j/pull/2170)
18+
* Add support for code generation of custom error type introduced with `solidity v0.8.4` [#2173](https://github.com/LFDT-web3j/web3j/pull/2173)
1819

1920

2021
### BREAKING CHANGES
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2019 Web3 Labs Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package org.web3j.abi;
14+
15+
import java.util.List;
16+
import java.util.stream.Collectors;
17+
18+
import org.web3j.abi.datatypes.CustomError;
19+
import org.web3j.abi.datatypes.Type;
20+
import org.web3j.crypto.Hash;
21+
import org.web3j.utils.Numeric;
22+
23+
/**
24+
* Ethereum custom error encoding. Further limited details are available <a
25+
* href="https://docs.soliditylang.org/en/develop/abi-spec.html#errors">here</a>.
26+
*/
27+
public class CustomErrorEncoder {
28+
29+
private CustomErrorEncoder() {}
30+
31+
public static String encode(CustomError error) {
32+
return calculateSignatureHash(buildErrorSignature(error.getName(), error.getParameters()));
33+
}
34+
35+
static <T extends Type> String buildErrorSignature(
36+
String errorName, List<TypeReference<T>> parameters) {
37+
38+
StringBuilder result = new StringBuilder();
39+
result.append(errorName);
40+
result.append("(");
41+
String params =
42+
parameters.stream().map(Utils::getTypeName).collect(Collectors.joining(","));
43+
result.append(params);
44+
result.append(")");
45+
return result.toString();
46+
}
47+
48+
public static String calculateSignatureHash(String errorSignature) {
49+
byte[] input = errorSignature.getBytes();
50+
byte[] hash = Hash.sha3(input);
51+
return Numeric.toHexString(hash);
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright 2019 Web3 Labs Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package org.web3j.abi.datatypes;
14+
15+
import java.util.List;
16+
17+
import org.web3j.abi.TypeReference;
18+
19+
import static org.web3j.abi.Utils.convert;
20+
21+
/** CustomError wrapper type. */
22+
public class CustomError {
23+
private String name;
24+
private List<TypeReference<Type>> parameters;
25+
26+
public CustomError(String name, List<TypeReference<?>> parameters) {
27+
this.name = name;
28+
this.parameters = convert(parameters);
29+
}
30+
31+
public String getName() {
32+
return name;
33+
}
34+
35+
public List<TypeReference<Type>> getParameters() {
36+
return parameters;
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2019 Web3 Labs Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package org.web3j.abi;
14+
15+
import java.util.Arrays;
16+
import java.util.List;
17+
18+
import org.junit.jupiter.api.Test;
19+
20+
import org.web3j.abi.datatypes.Address;
21+
import org.web3j.abi.datatypes.CustomError;
22+
import org.web3j.abi.datatypes.DynamicArray;
23+
import org.web3j.abi.datatypes.Utf8String;
24+
import org.web3j.abi.datatypes.generated.Uint256;
25+
26+
import static org.junit.jupiter.api.Assertions.assertEquals;
27+
import static org.web3j.abi.Utils.convert;
28+
29+
public class CustomErrorEncoderTest {
30+
@Test
31+
public void testCalculateSignatureHash() {
32+
assertEquals(
33+
CustomErrorEncoder.calculateSignatureHash("InvalidAccess(address,string,uint256)"),
34+
("0xcb5157bf1b439b9573ea7a95f7c00cc33f832ed728345c2bd29146ce58bbab57"));
35+
36+
assertEquals(
37+
CustomErrorEncoder.calculateSignatureHash("RandomError(address[],bytes)"),
38+
("0xbf37b77ddf0fbbf29ee6a3ebda3d177c2d438123b10571806c57958230d9f905"));
39+
}
40+
41+
@Test
42+
public void testEncode() {
43+
CustomError error =
44+
new CustomError(
45+
"InvalidAccess",
46+
Arrays.<TypeReference<?>>asList(
47+
new TypeReference<Address>() {},
48+
new TypeReference<Utf8String>() {},
49+
new TypeReference<Uint256>() {}));
50+
51+
assertEquals(
52+
CustomErrorEncoder.encode(error),
53+
"0xcb5157bf1b439b9573ea7a95f7c00cc33f832ed728345c2bd29146ce58bbab57");
54+
}
55+
56+
@Test
57+
public void testBuildErrorSignature() {
58+
List<TypeReference<?>> parameters =
59+
Arrays.<TypeReference<?>>asList(
60+
new TypeReference<Address>() {},
61+
new TypeReference<Utf8String>() {},
62+
new TypeReference<Uint256>() {});
63+
64+
assertEquals(
65+
"InvalidAccess(address,string,uint256)",
66+
CustomErrorEncoder.buildErrorSignature("InvalidAccess", convert(parameters)));
67+
}
68+
69+
@Test
70+
void testBuildErrorSignatureWithDynamicStructs() {
71+
List<TypeReference<?>> parameters =
72+
Arrays.asList(
73+
new TypeReference<AbiV2TestFixture.Nazz>() {},
74+
new TypeReference<AbiV2TestFixture.Foo>() {});
75+
76+
assertEquals(
77+
"DynamicStructError((((string,string)[])[],uint256),(string,string))",
78+
CustomErrorEncoder.buildErrorSignature("DynamicStructError", convert(parameters)));
79+
}
80+
81+
@Test
82+
void testBuildErrorSignatureWithDynamicArrays() {
83+
List<TypeReference<?>> parameters =
84+
Arrays.asList(new TypeReference<DynamicArray<AbiV2TestFixture.Nazz>>() {});
85+
86+
assertEquals(
87+
"DynamicArrayError((((string,string)[])[],uint256)[])",
88+
EventEncoder.buildMethodSignature("DynamicArrayError", convert(parameters)));
89+
}
90+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2020 Web3 Labs Ltd.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package org.web3j.abi.datatypes;
14+
15+
import java.util.Arrays;
16+
import java.util.Iterator;
17+
import java.util.List;
18+
19+
import org.junit.jupiter.api.Test;
20+
21+
import org.web3j.abi.TypeReference;
22+
import org.web3j.abi.datatypes.generated.Uint256;
23+
24+
import static org.junit.jupiter.api.Assertions.assertEquals;
25+
26+
public class CustomErrorTest {
27+
28+
@Test
29+
public void testCreation() {
30+
31+
List<TypeReference<?>> parameters =
32+
Arrays.<TypeReference<?>>asList(
33+
new TypeReference<Address>() {}, new TypeReference<Uint256>() {});
34+
CustomError event = new CustomError("MyError", parameters);
35+
36+
assertEquals(event.getName(), "MyError");
37+
38+
Iterator<TypeReference<?>> expectedParameter = parameters.iterator();
39+
for (TypeReference<?> actualParameter : event.getParameters()) {
40+
assertEquals(expectedParameter.next(), actualParameter);
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)