argentlabs / web3.swift

Ethereum Swift API with support for smart contracts, ENS & ERC20
MIT License
674 stars 169 forks source link

Sign typed data is not working with custom type array - basically V4 support #277

Closed joshuajiangdev closed 1 year ago

joshuajiangdev commented 1 year ago

When we tried to get signablehash from the following typed data from OpenSea.

{
  "types": {
    "EIP712Domain": [
      {
        "name": "name",
        "type": "string"
      },
      {
        "name": "version",
        "type": "string"
      },
      {
        "name": "chainId",
        "type": "uint256"
      },
      {
        "name": "verifyingContract",
        "type": "address"
      }
    ],
    "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"
      }
    ],
    "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"
      }
    ],

  },
  "primaryType": "OrderComponents",
  "domain": {
    "name": "Seaport",
    "version": "1.1",
    "chainId": "137",
    "verifyingContract": "0x00000000006c3852cbEf3e08E8dF289169EdE581"
  },
  "message": {
    "offerer": "0x1fB4b0D6EB80142a6d4893D20d541b235c314f0A",
    "offer": [
      {
        "itemType": "1",
        "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
        "identifierOrCriteria": "0",
        "startAmount": "900000000000000",
        "endAmount": "900000000000000"
      }
    ],
    "consideration": [
      {
        "itemType": "2",
        "token": "0xa9a6A3626993D487d2Dbda3173cf58cA1a9D9e9f",
        "identifierOrCriteria": "59091204723763704856388986543321552591754523831551465717007213448841304074849",
        "startAmount": "1",
        "endAmount": "1",
        "recipient": "0x1fB4b0D6EB80142a6d4893D20d541b235c314f0A"
      },
      {
        "itemType": "1",
        "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
        "identifierOrCriteria": "0",
        "startAmount": "22500000000000",
        "endAmount": "22500000000000",
        "recipient": "0x0000a26b00c1F0DF003000390027140000fAa719"
      }
    ],
    "startTime": "1668033203",
    "endTime": "1668292398",
    "orderType": "0",
    "zone": "0x0000000000000000000000000000000000000000",
    "zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "salt": "24446860302761739304752683030156737591518664810215442929813510023260621276899",
    "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000",
    "totalOriginalConsiderationItems": "2",
    "counter": "0"
  }
}

We are getting error in parseAtomicType under

guard let abiType = ABIRawType(rawValue: type) else {
            throw ABIError.invalidValue
}

where data is equal to

[
  {
    "itemType" : "1",
    "endAmount" : "900000000000000",
    "identifierOrCriteria" : "0",
    "token" : "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
    "startAmount" : "900000000000000"
  }
]

and type is OfferItem[]. This seems to be a match, the only issue here is this should not be in parseAtomicType because it seems like ABIRawType is only support RawType and passing in OfferItem will result a invalidValue (Maybe should be invalidType) error.

PS.

We are also trying to setup a simpler message:

            {
              "domain": {
                "chainId": "137",
                "name": "Ether Mail",
                "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
                "version": "1"
              },
              "message": {
                "contents": "Hello, Bob!",
                "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"
                  }
                ],
                "Mail": [
                  {
                    "name": "from",
                    "type": "Person"
                  },
                  {
                    "name": "to",
                    "type": "Person[]"
                  },
                  {
                    "name": "contents",
                    "type": "string"
                  }
                ],
                "Person": [
                  {
                    "name": "name",
                    "type": "string"
                  },
                  {
                    "name": "wallets",
                    "type": "address[]"
                  }
                ]
              }
            }

Seems this one is not working.

joshuajiangdev commented 1 year ago

I have implemented my own version here: https://github.com/joshuajiangdev/web3.swift-typeddata-v4/commit/8369ff744d438bc7c5fceaa84798c5a951d2b6f8

Let me know if you want me to submit a pull request. The newly added test cases are cross verified with @metamask/eth-sig-util.

DarthMike commented 1 year ago

Hi @joshuajiangdev yes please a PR would be great.