1

I'm using web3j library i want to sign a structured message butmy code return wrong signature (my code work for signTypedData_v3 and return currect signature) but how can i modify my code to can sign signTypedData_v4 messages ?

fun main() {
        //  private key
        val privateKey = "0...
    
        // Message data
        val message = """
           {"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"OrderComponents":[{"name":"offerer","type":"address"},{"name":"zone","type":"address"},{"name":"offer","type":"OfferItem[]"},{"name":"consideration","type":"ConsiderationItem[]"},{"name":"orderType","type":"uint8"},{"name":"startTime","type":"uint256"},{"name":"endTime","type":"uint256"},{"name":"zoneHash","type":"bytes32"},{"name":"salt","type":"uint256"},{"name":"conduitKey","type":"bytes32"},{"name":"counter","type":"uint256"}],"OfferItem":[{"name":"itemType","type":"uint8"},{"name":"token","type":"address"},{"name":"identifierOrCriteria","type":"uint256"},{"name":"startAmount","type":"uint256"},{"name":"endAmount","type":"uint256"}],"ConsiderationItem":[{"name":"itemType","type":"uint8"},{"name":"token","type":"address"},{"name":"identifierOrCriteria","type":"uint256"},{"name":"startAmount","type":"uint256"},{"name":"endAmount","type":"uint256"},{"name":"recipient","type":"address"}]},"primaryType":"OrderComponents","domain":{"name":"Seaport","version":"1.5","chainId":"137","verifyingContract":"0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC"},"message":{"offerer":"0x54ffab13A4852F81e2feB184918c115604b7bfbA","offer":[{"itemType":"3","token":"0x44b3f42e2BF34F62868Ff9e9dAb7C2F807ba97Cb","identifierOrCriteria":"45","startAmount":"1","endAmount":"1"}],"consideration":[{"itemType":"0","token":"0x0000000000000000000000000000000000000000","identifierOrCriteria":"0","startAmount":"925000000000000000","endAmount":"925000000000000000","recipient":"0x54ffab13A4852F81e2feB184918c115604b7bfbA"},{"itemType":"0","token":"0x0000000000000000000000000000000000000000","identifierOrCriteria":"0","startAmount":"25000000000000000","endAmount":"25000000000000000","recipient":"0x0000a26b00c1F0DF003000390027140000fAa719"},{"itemType":"0","token":"0x0000000000000000000000000000000000000000","identifierOrCriteria":"0","startAmount":"50000000000000000","endAmount":"50000000000000000","recipient":"0x99F1117F13e072b299942037E6A5d1469912B47A"}],"startTime":"1710071322","endTime":"1712749722","orderType":"1","zone":"0x0000000000000000000000000000000000000000","zoneHash":"0x0000000000000000000000000000000000000000000000000000000000000000","salt":"24446860302761739304752683030156737591518664810215442929800495252339539996469","conduitKey":"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000","totalOriginalConsiderationItems":"3","counter":"0"}}
        """.trimIndent()
    
        // Parse your private key to Credentials
        val credentials = Credentials.create(privateKey)
    
        val hash = StructuredDataEncoder(message).hashStructuredData().clone()
    
        val signature = Sign.signMessage(hash, credentials.ecKeyPair, false)
    
    
    println(Numeric.toHexString(signature.r+signature.s+signature.v))
    
    }
1
  • please check the solution below!
    – Mila A
    Commented Mar 14 at 16:34

1 Answer 1

1

You have totalOriginalConsiderationItems in the primary message that you pass in to sign, but it is missing in the types field:

missing-property-eip-712-signature-kotlin-web3j


The type and the corresponding values do not match.

A fixed message with a fixed types object is the following:

{
    "types":{
       "EIP712Domain":[
          {
             "name":"name",
             "type":"string"
          },
          {
             "name":"version",
             "type":"string"
          },
          {
             "name":"chainId",
             "type":"uint256"
          },
          {
             "name":"verifyingContract",
             "type":"address"
          }
       ],
       "OrderComponents":[
          {
             "name":"offerer",
             "type":"address"
          },
          {
             "name":"zone",
             "type":"address"
          },
          {
             "name":"offer",
             "type":"OfferItem[]"
          },
          {
             "name":"consideration",
             "type":"ConsiderationItem[]"
          },
          {
             "name":"orderType",
             "type":"uint8"
          },
          {
             "name":"startTime",
             "type":"uint256"
          },
          {
             "name":"endTime",
             "type":"uint256"
          },
          {
             "name":"zoneHash",
             "type":"bytes32"
          },
          {
             "name":"salt",
             "type":"uint256"
          },
          {
             "name":"conduitKey",
             "type":"bytes32"
          },
          {
            "name": "totalOriginalConsiderationItems",
            "type": "uint128"
          },
          {
             "name":"counter",
             "type":"uint256"
          }
       ],
       "OfferItem":[
          {
             "name":"itemType",
             "type":"uint8"
          },
          {
             "name":"token",
             "type":"address"
          },
          {
             "name":"identifierOrCriteria",
             "type":"uint256"
          },
          {
             "name":"startAmount",
             "type":"uint256"
          },
          {
             "name":"endAmount",
             "type":"uint256"
          }
       ],
       "ConsiderationItem":[
          {
             "name":"itemType",
             "type":"uint8"
          },
          {
             "name":"token",
             "type":"address"
          },
          {
             "name":"identifierOrCriteria",
             "type":"uint256"
          },
          {
             "name":"startAmount",
             "type":"uint256"
          },
          {
             "name":"endAmount",
             "type":"uint256"
          },
          {
             "name":"recipient",
             "type":"address"
          }
       ]
    },
    "primaryType":"OrderComponents",
    "domain":{
       "name":"Seaport",
       "version":"1.5",
       "chainId":"137",
       "verifyingContract":"0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC"
    },
    "message":{
       "offerer":"0x54ffab13A4852F81e2feB184918c115604b7bfbA",
       "offer":[
          {
             "itemType":"3",
             "token":"0x44b3f42e2BF34F62868Ff9e9dAb7C2F807ba97Cb",
             "identifierOrCriteria":"45",
             "startAmount":"1",
             "endAmount":"1"
          }
       ],
       "consideration":[
          {
             "itemType":"0",
             "token":"0x0000000000000000000000000000000000000000",
             "identifierOrCriteria":"0",
             "startAmount":"925000000000000000",
             "endAmount":"925000000000000000",
             "recipient":"0x54ffab13A4852F81e2feB184918c115604b7bfbA"
          },
          {
             "itemType":"0",
             "token":"0x0000000000000000000000000000000000000000",
             "identifierOrCriteria":"0",
             "startAmount":"25000000000000000",
             "endAmount":"25000000000000000",
             "recipient":"0x0000a26b00c1F0DF003000390027140000fAa719"
          },
          {
             "itemType":"0",
             "token":"0x0000000000000000000000000000000000000000",
             "identifierOrCriteria":"0",
             "startAmount":"50000000000000000",
             "endAmount":"50000000000000000",
             "recipient":"0x99F1117F13e072b299942037E6A5d1469912B47A"
          }
       ],
       "startTime":"1710071322",
       "endTime":"1712749722",
       "orderType":"1",
       "zone":"0x0000000000000000000000000000000000000000",
       "zoneHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
       "salt":"24446860302761739304752683030156737591518664810215442929800495252339539996469",
       "conduitKey":"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
       "totalOriginalConsiderationItems":"3",
       "counter":"0"
    }
 }

Hopefully, that solves your problem with Web3j & Kotlin typed v4 signature (signtypeddata_v4) signing. :)


(Edited)

Does at least signing this simple message work?

{"domain":{"chainId":1,"name":"Ether Mail","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","version":"1"},"message":{"contents":"Hello, Bob!","attachedMoneyInEth":4.2,"from":{"name":"Cow","wallets":["0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826","0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF"]},"to":[{"name":"Bob","wallets":["0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB","0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57","0xB0B0b0b0b0b0B000000000000000000000000000"]}]},"primaryType":"Mail","types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Group":[{"name":"name","type":"string"},{"name":"members","type":"Person[]"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person[]"},{"name":"contents","type":"string"}],"Person":[{"name":"name","type":"string"},{"name":"wallets","type":"address[]"}]}}

P.S. It'll help better understand where the problem lies.

Please try it.


(Edit):

Here's how you can do that with server-side NodeJS, considering you have an Ethereum private key, and with a server-side (NPM) @metamask/eth-sig-util package:

const { signTypedData, SignTypedDataVersion } = require("@metamask/eth-sig-util");

const signatureResult = signTypedData({
version: SignTypedDataVersion.V4,
data: {"domain":{"chainId":1,"name":"Ether Mail","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","version":"1"},"message":{"contents":"Hello, Bob!","attachedMoneyInEth":4.2,"from":{"name":"Cow","wallets":["0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826","0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF"]},"to":[{"name":"Bob","wallets":["0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB","0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57","0xB0B0b0b0b0b0B000000000000000000000000000"]}]},"primaryType":"Mail","types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Group":[{"name":"name","type":"string"},{"name":"members","type":"Person[]"}],"Mail":[{"name":"from","type":"Person"},{"name":"to","type":"Person[]"},{"name":"contents","type":"string"}],"Person":[{"name":"name","type":"string"},{"name":"wallets","type":"address[]"}]}},
privateKey: BigInt(`0xd9518676d87bc64f9e43f6ad0fdaedac08eaf8ad49361f586b0887d001b4978e`)
});

console.log({signatureResult});

The output result is:

$ node index.js
{
  signatureResult: '0x8abc89d7ff51e002e24de76507418210632d1fc27c10e9677c2ccd9c6d37c7ff5f6442ae375d3623b0
bf2ad1d610ab3bb7e7106286677b56e43d8d694441ca6f1c'
}

As you can see, if the property in the filled values is not specified in the types field of the message to sign, then an error will be thrown:

node_modules\@metamask\eth-sig-util\dist\sign-typed-data.js:150
throw new Error(`missing value for field ${name} of type ${type}`);
8
  • i got this message from opnsea.io , i can't change it...
    – luntik
    Commented Mar 14 at 16:47
  • Why not edit the types:OrderComponents struct's field though?
    – Mila A
    Commented Mar 14 at 17:08
  • You cannot edit the data, but you can edit the type specification, considering it doesn't match with the data
    – Mila A
    Commented Mar 14 at 17:09
  • 1
    Let us continue this discussion in chat.
    – luntik
    Commented Mar 14 at 17:39
  • 1
    @luntik, please accept my answer if it was helpful :)
    – Mila A
    Commented Mar 14 at 19:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.