magiclabs/magic-js

`eth_signTypedData_v4` fails if the message params are stringified instead of sent as an object

nickick opened this issue ยท 24 comments

โœ… Prerequisites

  • Did you perform a cursory search of open issues? Is this bug already reported elsewhere?
  • Are you running the latest SDK version?
  • Are you reporting to the correct repository (magic-sdk)?

๐Ÿ› Description

eth_signTypedData_v4 fails if the message params are stringified instead of sent as an object. Breaks on v17 and v18

๐Ÿงฉ Steps to Reproduce

Gist | Codesandbox

To reproduce, request eth_signTypedData_v4 while passing a stringified object in its params.

const message = {
  ...
}

const { publicAddress } = await magic.user.getInfo();
magic.rpcProvider.request({
  method: "eth_signTypedData_v4",
  params: [publicAddress, JSON.stringify(message)]
});

if I send it as params: [publicAddress, message], it works as expected. However, Metamask expects it as params: [publicAddress, JSON.stringify(message)]. We're working with an SDK that makes these signature requests, so it would be difficult to change it directly.

๐Ÿค” Expected behavior

I expect sending it as JSON.stringify(message) to pop up a signature transaction window. This how Metamask expects it.

๐Ÿ˜ฎ Actual behavior

The UI breaks, with the MagicLink iframe frozen over the UI, and this minified errors show up:

Error: Minified React error #301; visit https://reactjs.org/docs/error-decoder.html?invariant=301 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
    at Yi (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:233470)
    at rs (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:286726)
    at Zc (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:282342)
    at Uc (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:282270)
    at $c (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:282123)
    at Tc (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:278435)
    at _c (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:277387)
    at w (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:301845)
    at L (app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2:302209)
    at m.<computed> (app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2:738716)
(anonymous) @ app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2
Ze @ app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2
console.error @ app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2
console.<computed> @ app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2
Vu @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
n.callback @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
li @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
Yl @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
Zl @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
Wl @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
Xc @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
Gc @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
_c @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
w @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
L @ app.chunk~vendor~react.a7eafcd306300c9d25bc.js:2
m.<computed> @ app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2
E @ app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2
S @ app.chunk~vendor~fad58de7366495db4650cfefac2fcd61.906262e51ffe63ccda63.js:2

๐Ÿ’ป Code Sample

Codesandbox

๐ŸŒŽ Environment

Software Version(s)
magic-sdk v18, v17
Browser chrome
yarn 1.22.19
Operating System OSX

Hi @nickick ,

Thank you for opening this issue. I have escalated this issue to the team and will continue to follow up on this thread.

nick commented

This is also broken in your demo environment: https://codesandbox.io/s/github/magiclabs/magic-demo-react-web3

Clicking 'Sign Typed Data v4' hangs the app.

Thank you @nick , it is failing for the same reason which is that the method is attempting to sign a JSON stringified payload.

nick commented

@am-hernandez any ideas on when this might get resolved? Users of https://marketplace.pudgyworld.com have been unable to create listings for a while now due to this bug ๐Ÿ˜ฌ

Thanks!

@nick , The quickest workaround would be to send the payload object without stringifying it. Would that cause too much friction devx-wise?

nick commented

Since it's the wagmi library that's doing the stringifying of the payload... we'd have to patch it there which isn't easy

@nick Thank you, that makes sense. Right now the rough timeline will be about two weeks from now, which is subject to change. I will follow up in this issue thread with updates as I receive them.

@am-hernandez thanks for the updating with an ETA on this. For ref, this is preventing anyone from using Magic.Link on Pudgy Penguin and other marketplaces from listing their NFTs or placing offers, pretty core pieces to any marketplace.

ayv8er commented

We'll aim for quicker resolution, we'll update here once this is resolved.

nick commented

Thank you!

@nick We have pushed out a change that resolves this issue. Would you kindly try it out and let us know if you see this resolved on your end?

@am-hernandez looks like this specific error was fixed! However, we're now seeing a new issue: the confirm action tab that opens up hangs and times out. Screenshot:

Screenshot 2023-06-29 at 6 30 43 PM

It looks like there's a 400 from a POST to Magic in the network tab, here's the curl:

curl 'https://api.magic.link/v1/core/user/action/confirm/begin' \
  -H 'authority: api.magic.link' \
  -H 'accept: application/json, text/plain, */*' \
  -H 'accept-language: en_us' \
  -H 'authorization: Bearer e1c05713170aba07fd23e7bd34b8a481ffcdedea3702bd30bd491585c5551767.d_R3tKRbCxnAeRFDKzgCyl9HjdM' \
  -H 'content-type: application/json;charset=UTF-8' \
  -H 'cookie: __cf_bm=iPOibZVQudwof3uGPptj69IQDGwp.YTtZhedNZIADXc-1688080742-0-AU6dDoNenfjQ3HPggKhpCcz29AC1fJiO52ted04oCIZuUS90wSBPCumNQnrAWlmzqsUefGLOrdiaavBCnOZSrXA=; __cfruid=940dbc73e7219d8602daec402e98c9846bcf337e-1688080742' \
  -H 'origin: https://auth.magic.link' \
  -H 'referer: https://auth.magic.link/' \
  -H 'sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' \
  -H 'x-amzn-trace-id: Root=46ca5d14-ba44-4799-b4d8-cd6102eb403a' \
  -H 'x-fortmatic-network: mainnet' \
  -H 'x-magic-api-key: pk_live_165299F5B31896DF' \
  -H 'x-magic-bundle-id: BundleIDMissing' \
  -H 'x-magic-referrer: https://marketplace.pudgyworld.com' \
  -H 'x-magic-sdk: magic-sdk' \
  -H 'x-magic-trace-id: 46ca5d14-ba44-4799-b4d8-cd6102eb403a' \
  --data-raw '{"auth_user_id":"EoyZ8FJuPAs3-eW8PeCPaOBeRjolch_8mn4BLYpYegs=","action":"SIGN_MESSAGE","payload":{"message":"{\"domain\":{\"name\":\"Seaport\",\"version\":\"1.5\",\"chainId\":137,\"verifyingContract\":\"0x00000000000000adc04c56bf30ac9d3c0aaf14dc\"},\"primaryType\":\"OrderComponents\",\"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\"}]},\"message\":{\"kind\":\"single-token\",\"offerer\":\"0xc5c78ace286862b22b0c332e4e296785794581a0\",\"zone\":\"0x0000000000000000000000000000000000000000\",\"offer\":[{\"itemType\":3,\"token\":\"0x84047392538009c3d3da0aa76a098b44e1ea5771\",\"identifierOrCriteria\":\"39\",\"startAmount\":\"1\",\"endAmount\":\"1\"}],\"consideration\":[{\"itemType\":1,\"token\":\"0x7ceb23fd6bc0add59e62ac25578270cff1b9f619\",\"identifierOrCriteria\":\"0\",\"startAmount\":\"1020616223532145\",\"endAmount\":\"1020616223532145\",\"recipient\":\"0xc5c78ace286862b22b0c332e4e296785794581a0\"},{\"itemType\":1,\"token\":\"0x7ceb23fd6bc0add59e62ac25578270cff1b9f619\",\"identifierOrCriteria\":\"0\",\"startAmount\":\"53716643343797\",\"endAmount\":\"53716643343797\",\"recipient\":\"0x3839295107334f9ce126d0867d2acf091794c0ee\"}],\"orderType\":1,\"startTime\":1688081286,\"endTime\":1690673346,\"zoneHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"salt\":\"16184194831101861726006543015570503459110302092569578533765680930406401771994\",\"conduitKey\":\"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000\",\"counter\":\"0\",\"signature\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}}","request_domain":"https://marketplace.pudgyworld.com"}}' \
  --compressed

and the response:

{
    "data": {},
    "error_code": "BAD_REQUEST",
    "message": "Bad Request. Please check your request URI and arguments. Error message: Invalid payload.",
    "status": "failed"
}

Hi @nickick, do you have a time for when this error occurred? Also, would you let us know if this error is reproducible?

@am-hernandez it's reproducible, every time I try to list on our marketplace. I'm having the same 400 on that endpoint. I think I made that curl 30 minutes ago? I just made 2 requests more in the last 5 minutes as well.

Here's one I just made:

curl 'https://api.magic.link/v1/core/user/action/confirm/begin' \
  -H 'authority: api.magic.link' \
  -H 'accept: application/json, text/plain, */*' \
  -H 'accept-language: en_us' \
  -H 'authorization: Bearer 3fcf3e9a149b0612266800bca6fd9c70137b6f12954fed4ff3b2f12064dc170d.CmCUC-DtOtEWsiRrX9WqhzS7YMI' \
  -H 'content-type: application/json;charset=UTF-8' \
  -H 'cookie: __cf_bm=b97WjC537GIlaEd..g6GMoztFNi7xzSurAIJDMWsxOY-1688082828-0-Adf7UofT1zw+wNggiGtQ+tK5y2ZPAuqJcAGLKNagWo3vn1U+omFnS2ezv9gzGrtlOClboBBhqx+1mfNZwk8e9X8=; __cfruid=cb994155d198bfdff4292cbab7499217daf1cb3f-1688082828' \
  -H 'origin: https://auth.magic.link' \
  -H 'referer: https://auth.magic.link/' \
  -H 'sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Windows"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36' \
  -H 'x-amzn-trace-id: Root=bff5b05e-66de-4fdc-8314-956f0afebca4' \
  -H 'x-fortmatic-network: mainnet' \
  -H 'x-magic-api-key: pk_live_165299F5B31896DF' \
  -H 'x-magic-bundle-id: BundleIDMissing' \
  -H 'x-magic-referrer: https://marketplace.pudgyworld.com' \
  -H 'x-magic-sdk: magic-sdk' \
  -H 'x-magic-trace-id: bff5b05e-66de-4fdc-8314-956f0afebca4' \
  --data-raw '{"auth_user_id":"EoyZ8FJuPAs3-eW8PeCPaOBeRjolch_8mn4BLYpYegs=","action":"SIGN_MESSAGE","payload":{"message":"{\"domain\":{\"name\":\"Seaport\",\"version\":\"1.5\",\"chainId\":137,\"verifyingContract\":\"0x00000000000000adc04c56bf30ac9d3c0aaf14dc\"},\"primaryType\":\"OrderComponents\",\"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\"}]},\"message\":{\"kind\":\"single-token\",\"offerer\":\"0xc5c78ace286862b22b0c332e4e296785794581a0\",\"zone\":\"0x0000000000000000000000000000000000000000\",\"offer\":[{\"itemType\":1,\"token\":\"0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270\",\"identifierOrCriteria\":\"0\",\"startAmount\":\"7000000000000000\",\"endAmount\":\"7000000000000000\"}],\"consideration\":[{\"itemType\":3,\"token\":\"0x84047392538009c3d3da0aa76a098b44e1ea5771\",\"identifierOrCriteria\":\"39\",\"startAmount\":\"1\",\"endAmount\":\"1\",\"recipient\":\"0xc5c78ace286862b22b0c332e4e296785794581a0\"},{\"itemType\":1,\"token\":\"0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270\",\"identifierOrCriteria\":\"0\",\"startAmount\":\"350000000000000\",\"endAmount\":\"350000000000000\",\"recipient\":\"0x3839295107334f9ce126d0867d2acf091794c0ee\"}],\"orderType\":1,\"startTime\":1688083110,\"endTime\":1690675166,\"zoneHash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"salt\":\"16184194831101861726006543015570503459260680720835327239272339314674758051905\",\"conduitKey\":\"0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000\",\"counter\":\"0\",\"signature\":\"0x0000000000000000000000000000000000000000000000000000000000000000\"}}","request_domain":"https://marketplace.pudgyworld.com"}}' \
  --compressed

Thanks, @nickick . Are you able to repro this in a sandbox? I am not seeing this error when signing.

nick commented

If I edit utils/signTypedData-payload.ts in the sandbox and export the following in place of signTypedDataV4Payload, I am able to reproduce the error. The following is a standard payload for an OpenSea Seaport order:

export const signTypedDataV4Payload = {
  domain: {
    name: 'Seaport',
    version: '1.5',
    chainId: 1,
    verifyingContract: '0x00000000000000adc04c56bf30ac9d3c0aaf14dc'
  },
  primaryType: 'OrderComponents',
  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' }
    ]
  },
  message: {
    kind: 'single-token',
    offerer: '0x09fddbbaf37b19ca477649aeef6f4bb46b3dfb7b',
    zone: '0x0000000000000000000000000000000000000000',
    offer: [
      {
        itemType: 2,
        token: '0x524cab2ec69124574082676e6f654a18df49a048',
        identifierOrCriteria: '9437',
        startAmount: '1',
        endAmount: '1'
      }
    ],
    consideration: [
      {
        itemType: 0,
        token: '0x0000000000000000000000000000000000000000',
        identifierOrCriteria: '0',
        startAmount: '950000000000000000',
        endAmount: '950000000000000000',
        recipient: '0x09fddbbaf37b19ca477649aeef6f4bb46b3dfb7b'
      },
      {
        itemType: 0,
        token: '0x0000000000000000000000000000000000000000',
        identifierOrCriteria: '0',
        startAmount: '50000000000000000',
        endAmount: '50000000000000000',
        recipient: '0x2de038a402119bcbd49a4412c35f27670801ed4e'
      }
    ],
    orderType: 0,
    startTime: 1688092553,
    endTime: 1688096213,
    zoneHash:
      '0x0000000000000000000000000000000000000000000000000000000000000000',
    salt: '16184194831101861726006543015570503459298694222654417638899507155898314739881',
    conduitKey:
      '0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000',
    counter: '0',
    signature:
      '0x0000000000000000000000000000000000000000000000000000000000000000'
  }
}

@nick Thank you! I was also able to repro the error in our sandbox demo with the payload you provided. It only errors with this payload as a JSON string, which is relevant to this issue so we'll keep this open.

Thanks @nick! And @am-hernandez thanks for staying on top of this.

nick commented

@am-hernandez @ayv8er Another theory is that this bug is due to the size of the payload.

Modifying the original sandbox data again, the following payload works:

export const signTypedDataV4Payload = {
  types: {
    EIP712Domain: [
      { name: 'name', type: 'string', },
      { name: 'version', type: 'string', },
      { name: 'verifyingContract', type: 'address', },
    ],
    Greeting: [
      { name: 'contents', type: 'string' },
      { name: 'contents2', type: 'string' },
      { name: 'contents3', type: 'string' },
    ],
  },
  primaryType: 'Greeting',
  domain: {
    name: 'Magic',
    version: '1',
    verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D',
  },
  message: {
    contents: 'Hello, from Magic!',
  },
}

whereas this one with one additional line in types.Greeting does not:

export const signTypedDataV4Payload = {
  types: {
    EIP712Domain: [
      { name: 'name', type: 'string', },
      { name: 'version', type: 'string', },
      { name: 'verifyingContract', type: 'address', },
    ],
    Greeting: [
      { name: 'contents', type: 'string' },
      { name: 'contents2', type: 'string' },
      { name: 'contents3', type: 'string' },
      { name: 'contents4', type: 'string' },
    ],
  },
  primaryType: 'Greeting',
  domain: {
    name: 'Magic',
    version: '1',
    verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D',
  },
  message: {
    contents: 'Hello, from Magic!',
  },
}
nick commented

It looks like you're encoding the signature request into the URL query params which is probably why messages over a certain length don't work

image

Hi @nick , thanks for digging into this. As I am awaiting a followup from my team I will share this info with them. When I have an update to share I will post here.

Thanks again and feel free to post context as it comes up on your end as I aim to do the same from my end.

Hi @nick ,

We have pushed changes to resolve this issue. I have given it a try with your payload and it works in my demo. Would you please let us know if this is resolved on your end?

Thank you!

thank you confirming the resolution via an external channel. Closing this issue!