From d349a797ba044d10344d83375bbc85ca4c78afbc Mon Sep 17 00:00:00 2001 From: Hampus Eriksson Date: Tue, 26 Sep 2023 08:53:22 +0200 Subject: [PATCH] Correctly encode structs without members The JSON RPC API specification for 'eth_signTypedData_v4' does not explicitly state that the required struct 'EIP712Domain' has to define any members [1]. The current implementation cannot correctly encode such a structure, as it assumes that at least one member has been parsed and added to the struct's string representation. This commit refactors the struct encoding function such that it now accepts structures that does not define any members. [1] https://eips.ethereum.org/EIPS/eip-712#specification-of-the-eth_signtypeddata-json-rpc --- .../org/web3j/crypto/StructuredDataEncoder.java | 9 +++------ .../java/org/web3j/crypto/StructuredDataTest.java | 14 ++++++++++++++ .../ValidMinimalStructuredData.json | 8 ++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 crypto/src/test/resources/structured_data_json_files/ValidMinimalStructuredData.json diff --git a/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java b/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java index ff9e3369e..143fcfdb1 100644 --- a/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java +++ b/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.StringJoiner; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -120,14 +121,10 @@ public Set getDependencies(String primaryType) { public String encodeStruct(String structName) { HashMap> types = jsonMessageObject.getTypes(); - StringBuilder structRepresentation = new StringBuilder(structName + "("); + StringJoiner structRepresentation = new StringJoiner(",", structName + "(", ")"); for (StructuredData.Entry entry : types.get(structName)) { - structRepresentation.append(String.format("%s %s,", entry.getType(), entry.getName())); + structRepresentation.add(String.format("%s %s", entry.getType(), entry.getName())); } - structRepresentation = - new StringBuilder( - structRepresentation.substring(0, structRepresentation.length() - 1)); - structRepresentation.append(")"); return structRepresentation.toString(); } diff --git a/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java b/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java index 5f15636b7..970f933a7 100644 --- a/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java +++ b/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java @@ -113,6 +113,20 @@ public void testEncodeType() throws IOException, RuntimeException { expectedTypeEncoding); } + @Test + public void testMinimalEncodeType() throws IOException, RuntimeException { + String validMinimalStructuredDataJSONFilePath = + "build/resources/test/" + + "structured_data_json_files/ValidMinimalStructuredData.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(validMinimalStructuredDataJSONFilePath)); + String expectedTypeEncoding = "EIP712Domain()"; + + assertEquals( + dataEncoder.encodeType(dataEncoder.jsonMessageObject.getPrimaryType()), + expectedTypeEncoding); + } + @Test public void testTypeHash() throws IOException, RuntimeException { StructuredDataEncoder dataEncoder = new StructuredDataEncoder(jsonMessageString); diff --git a/crypto/src/test/resources/structured_data_json_files/ValidMinimalStructuredData.json b/crypto/src/test/resources/structured_data_json_files/ValidMinimalStructuredData.json new file mode 100644 index 000000000..6444e1ba2 --- /dev/null +++ b/crypto/src/test/resources/structured_data_json_files/ValidMinimalStructuredData.json @@ -0,0 +1,8 @@ +{ + "types": { + "EIP712Domain": [] + }, + "primaryType": "EIP712Domain", + "domain": {}, + "message": {} +} \ No newline at end of file