From 8cb1dce3fd33bca222aadcc2378bb692180a8677 Mon Sep 17 00:00:00 2001 From: Davy Van Roy Date: Fri, 30 Oct 2020 14:07:47 +0100 Subject: [PATCH] add salt to EIP712 domain (#1260) * add salt to EIP-712 domain * ran `gradlew spotlessApply` --- .../java/org/web3j/crypto/StructuredData.java | 9 ++++- .../web3j/crypto/StructuredDataEncoder.java | 4 ++ .../org/web3j/crypto/StructuredDataTest.java | 15 +++++++ .../ValidStructuredDataWithSalt.json | 39 +++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 crypto/src/test/resources/structured_data_json_files/ValidStructuredDataWithSalt.json diff --git a/crypto/src/main/java/org/web3j/crypto/StructuredData.java b/crypto/src/main/java/org/web3j/crypto/StructuredData.java index 0dbf9e8db..ffe0e3c2f 100644 --- a/crypto/src/main/java/org/web3j/crypto/StructuredData.java +++ b/crypto/src/main/java/org/web3j/crypto/StructuredData.java @@ -48,17 +48,20 @@ static class EIP712Domain { private final String version; private final Uint256 chainId; private final Address verifyingContract; + private final String salt; @JsonCreator public EIP712Domain( @JsonProperty(value = "name") String name, @JsonProperty(value = "version") String version, @JsonProperty(value = "chainId") Uint256 chainId, - @JsonProperty(value = "verifyingContract") Address verifyingContract) { + @JsonProperty(value = "verifyingContract") Address verifyingContract, + @JsonProperty(value = "salt") String salt) { this.name = name; this.version = version; this.chainId = chainId; this.verifyingContract = verifyingContract; + this.salt = salt; } public String getName() { @@ -76,6 +79,10 @@ public Uint256 getChainId() { public Address getVerifyingContract() { return verifyingContract; } + + public String getSalt() { + return salt; + } } static class EIP712Message { diff --git a/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java b/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java index be1beb4bb..66a3b0696 100644 --- a/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java +++ b/crypto/src/main/java/org/web3j/crypto/StructuredDataEncoder.java @@ -362,6 +362,10 @@ public byte[] hashDomain() throws RuntimeException { data.put( "verifyingContract", ((HashMap) data.get("verifyingContract")).get("value")); + + if (data.get("salt") == null) { + data.remove("salt"); + } return sha3(encodeData("EIP712Domain", data)); } diff --git a/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java b/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java index dc7806ad9..34791eb5c 100644 --- a/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java +++ b/crypto/src/test/java/org/web3j/crypto/StructuredDataTest.java @@ -394,4 +394,19 @@ public void testDataNotPerfectArrayButDeclaredArrayInSchema() new StructuredDataEncoder(getResource(invalidStructuredDataJSONFilePath)); assertThrows(RuntimeException.class, dataEncoder::hashStructuredData); } + + @Test + public void testHashDomainWithSalt() throws RuntimeException, IOException { + String validStructuredDataWithSaltJSONFilePath = + "build/resources/test/" + + "structured_data_json_files/" + + "ValidStructuredDataWithSalt.json"; + StructuredDataEncoder dataEncoder = + new StructuredDataEncoder(getResource(validStructuredDataWithSaltJSONFilePath)); + byte[] structHashDomain = dataEncoder.hashDomain(); + String expectedDomainStructHash = + "0xbae4f6f7b9bfdfda060692099b0e1ccecd25d62b7c92cc9f3b907f33178b81e3"; + + assertEquals(Numeric.toHexString(structHashDomain), expectedDomainStructHash); + } } diff --git a/crypto/src/test/resources/structured_data_json_files/ValidStructuredDataWithSalt.json b/crypto/src/test/resources/structured_data_json_files/ValidStructuredDataWithSalt.json new file mode 100644 index 000000000..1a69d5c48 --- /dev/null +++ b/crypto/src/test/resources/structured_data_json_files/ValidStructuredDataWithSalt.json @@ -0,0 +1,39 @@ +{ + "types": { + "EIP712Domain": [ + {"name": "name", "type": "string"}, + {"name": "version", "type": "string"}, + {"name": "chainId", "type": "uint256"}, + {"name": "verifyingContract", "type": "address"}, + {"name": "salt", "type": "bytes32"} + ], + "Person": [ + {"name": "name", "type": "string"}, + {"name": "wallet", "type": "address"} + ], + "Mail": [ + {"name": "from", "type": "Person"}, + {"name": "to", "type": "Person"}, + {"name": "contents", "type": "string"} + ] + }, + "primaryType": "Mail", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", + "salt": "0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558" + }, + "message": { + "from": { + "name": "Cow", + "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" + }, + "to": { + "name": "Bob", + "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" + }, + "contents": "Hello, Bob!" + } +}