Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: ethers signTypedData returns incorrect signature / recovered address #7792

Closed
cieltan opened this issue Nov 14, 2023 · 9 comments · Fixed by #7886 or rainbow-me/browser-extension#1341
Assignees
Labels
external-contributor regression-prod-7.10.0 Regression bug that was found in production in release 7.10.0 regression-RC DEPRECATED: Please use "regresssion-RC-x.y.z" label instead regression-RC-7.12.5 release-7.12.5 Issue or pull request that will be included in release 7.12.5 Sev1-high An issue that may have caused fund loss or access to wallet in the past & may still be ongoing team-wallet-framework type-bug Something isn't working

Comments

@cieltan
Copy link

cieltan commented Nov 14, 2023

Describe the bug

Over the last week, when using the ethers signTypedData function on Metamask Mobile, the returned signature does not return the correct signer address when trying to recover it using the ethers verifyTypedData function.

This behavior on Metamask mobile is completely different from the desktop extension. When going through the same flow on desktop, the returned signature is correctly recovered with the correct address when using the verifyTypedData function.

This bug is affecting all users interacting/performing marketplace actions such as listing/delisting with NFT marketplaces based on the Avalanche network that require signing messages.

I'm just trying to get clarity as to how these functions might behave differently on mobile vs desktop. In the E2E metamask dapp, the signTypedData function seems to still work correctly.

Expected behavior

The ethers signTypedData function should returns a signature that can recover the signer on mobile. This function works as expected on desktop with the Metamask extension.

Screenshots/Recordings

No response

Steps to reproduce

  1. Go to any NFT marketplace that requires off-chain signing. (i.e. https://avax.hyperspace.xyz/, https://joepegs.com/)
  2. Try to list or delist any NFT in your account. The action will either silently fail or outright fail because of reasons stated above.

Error messages or log output

No response

Version

7.10.0

Build type

None

Device

iPhone 13 Pro Max

Operating system

iOS

Additional context

This is an example of how we're structuring the message to be signed. This is recoverable on desktop but not on Metamask Mobile.

const domain = {
      chainId: chainId,
      verifyingContract: exchangeContractAddress,
      name: 'ZeroEx',
      version: '1.0.0',
    };
const types = {
    [ERC721ORDER_STRUCT_NAME]: ERC721ORDER_STRUCT_ABI,
    Fee: FEE_ABI,
    Property: PROPERTY_ABI,
};
const value = order;
    
// signer is a JSONRPCSigner
    
const rawSignature = await signer._signTypedData(
      domain,
      types,
      value
);

Severity

No response

@cieltan cieltan added the type-bug Something isn't working label Nov 14, 2023
@metamaskbot metamaskbot added external-contributor regression-prod-7.10.0 Regression bug that was found in production in release 7.10.0 labels Nov 14, 2023
@cieltan cieltan changed the title [Bug]: Metamask Mobile ethers signTypedData returns incorrect signature / recovered address [Bug]: ethers signTypedData returns incorrect signature / recovered address Nov 14, 2023
@anaamolnar anaamolnar added team-confirmations-system DEPRECATED: please use "team-confirmations" label instead needs-triage Issues that require triage labels Nov 15, 2023
@sethkfman sethkfman added Sev2-normal An issue that may lead to users misunderstanding some limited risks they are taking and removed Sev2-normal An issue that may lead to users misunderstanding some limited risks they are taking labels Nov 15, 2023
@robpolak-cb
Copy link

Can confirm seeing similar issues with https://nft.coinbase.com .. Confirmed that switching wallets solved the issue for us.

@Gudahtt
Copy link
Member

Gudahtt commented Nov 16, 2023

Thanks for the report! We're trying to reproduce the issue but haven't had success yet. Could you share an example message that demonstrates the problem?

I see that you provided a partial example already, but quite a few details are missing (e.g. the ABI types and the example value)

@cieltan
Copy link
Author

cieltan commented Nov 16, 2023

Thanks for the report! We're trying to reproduce the issue but haven't had success yet. Could you share an example message that demonstrates the problem?

I see that you provided a partial example already, but quite a few details are missing (e.g. the ABI types and the example value)

Sure, here is a more expanded version of the snippet above.

export const ERC721ORDER_STRUCT_NAME = 'ERC721Order';

export const ERC721ORDER_STRUCT_ABI = [
  { type: 'uint8', name: 'direction' },
  { type: 'address', name: 'maker' },
  { type: 'address', name: 'taker' },
  { type: 'uint256', name: 'expiry' },
  { type: 'uint256', name: 'nonce' },
  { type: 'address', name: 'erc20Token' },
  { type: 'uint256', name: 'erc20TokenAmount' },
  { type: 'Fee[]', name: 'fees' },
  { type: 'address', name: 'erc721Token' },
  { type: 'uint256', name: 'erc721TokenId' },
  { type: 'Property[]', name: 'erc721TokenProperties' },
];

export const FEE_ABI = [
  { type: 'address', name: 'recipient' },
  { type: 'uint256', name: 'amount' },
  { type: 'bytes', name: 'feeData' },
];

export const PROPERTY_ABI = [
  { type: 'address', name: 'propertyValidator' },
  { type: 'bytes', name: 'propertyData' },
];

const exampleValue = {
    "direction": 0,
    "maker": "0xe17b0e1b433fa922d2db81c054c40a207b0f9bcf",
    "taker": "0x0000000000000000000000000000000000000000",
    "expiry": "2524604400",
    "nonce": "100131415900000000000000000000000000000057349237573513839986502369650552413525",
    "erc20Token": "0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7",
    "erc20TokenAmount": "1000000000000000000",
    "fees": [
        {
            "amount": "20000000000000000",
            "recipient": "0x87f45335268512cc5593d435e61df4d75b07d2a2",
            "feeData": "0x"
        },
        {
            "amount": "5000000000000000",
            "recipient": "0x91c1c72c21bed9d80cc28d926cac60d09dcbaf92",
            "feeData": "0x"
        }
    ],
    "erc721Token": "0x95008965fabbe94c9e6d64389069cc310e6c193e",
    "erc721TokenId": "1433",
    "erc721TokenProperties": []
}

@Gudahtt
Copy link
Member

Gudahtt commented Nov 16, 2023

Thanks, that was very helpful! I have been able to reproduce the problem

@Gudahtt Gudahtt added Sev1-high An issue that may have caused fund loss or access to wallet in the past & may still be ongoing and removed team-confirmations-system DEPRECATED: please use "team-confirmations" label instead needs-triage Issues that require triage labels Nov 20, 2023
@chrisleewilcox chrisleewilcox added release-blocker This bug is blocking the next release release-7.12.0 Issue or pull request that will be included in release 7.12.0 regression-RC DEPRECATED: Please use "regresssion-RC-x.y.z" label instead labels Nov 20, 2023
@Gudahtt Gudahtt removed release-blocker This bug is blocking the next release regression-RC DEPRECATED: Please use "regresssion-RC-x.y.z" label instead team-wallet-api-platform release-7.12.0 Issue or pull request that will be included in release 7.12.0 labels Nov 20, 2023
@metamaskbot metamaskbot added regression-RC DEPRECATED: Please use "regresssion-RC-x.y.z" label instead release-7.12.0 Issue or pull request that will be included in release 7.12.0 labels Nov 20, 2023
Gudahtt added a commit that referenced this issue Nov 20, 2023
In v7.10.0, signatures including a `bytes` field with the value `0x`
were being encoded differently than before. Previously the string `0x`
was interpreted as an "empty" hex number, but as of v7.10.0 they were
encoded as the string "0x". This change was not intentional, and it
resulted in invalid signatures.

This problem was introduced in `@metamask/eth-sig-util@6.0.1` (see here
for details: MetaMask/eth-sig-util#340). This
package was introduced to mobile when `@metamask/keyring-controller`
was updated to v6 (#7267).
The keyrings themselves still use `@metamask/eth-sig-util@5.0.1`, but
the `KeyringController` is signing these messages directly rather than
delegating to the keyrings, which is why the newer
`@metamask/eth-sig-util` package is used here.

This has been resovled by patching `@metamask/keyring-controller` to
delegate signing typed messages to the keyrings. The very next release
of that package includes that change anyway. We will wait until this
bug is fixed before updating `@metamask/eth-sig-util` in the keyrings.

Fixes #7792
Gudahtt added a commit to MetaMask/test-dapp that referenced this issue Nov 21, 2023
The example `eth_signTypedData_v4` message has been updated to include
a field that can reproduce this bug: MetaMask/metamask-mobile#7792
That signing bug results in invalid signatures for any messages that
include a `bytes` field with the value `0x`.
Gudahtt added a commit that referenced this issue Nov 21, 2023
In v7.10.0, signatures including a `bytes` field with the value `0x`
were being encoded differently than before. Previously the string `0x`
was interpreted as an "empty" hex number, but as of v7.10.0 they were
encoded as the string "0x". This change was not intentional, and it
resulted in invalid signatures.

This problem was introduced in `@metamask/eth-sig-util@6.0.1` (see here
for details: MetaMask/eth-sig-util#340). This
package was introduced to mobile when `@metamask/keyring-controller`
was updated to v6 (#7267).
The keyrings themselves still use `@metamask/eth-sig-util@5.0.1`, but
the `KeyringController` is signing these messages directly rather than
delegating to the keyrings, which is why the newer
`@metamask/eth-sig-util` package is used here.

This has been resolved by patching `@metamask/keyring-controller` to
delegate signing typed messages to the keyrings. The very next release
of that package includes that change anyway. We will wait until this
bug is fixed before updating `@metamask/eth-sig-util` in the keyrings.

Fixes #7792
Gudahtt added a commit to MetaMask/test-dapp that referenced this issue Nov 22, 2023
The example `eth_signTypedData_v4` message has been updated to include
a field that can reproduce this bug: MetaMask/metamask-mobile#7792
That signing bug results in invalid signatures for any messages that
include a `bytes` field with the value `0x`.
Gudahtt added a commit that referenced this issue Nov 29, 2023
## **Description**

In v7.10.0, signatures including a `bytes` field with the value `0x`
were being encoded differently than before. Previously the string `0x`
was interpreted as an "empty" hex number, but as of v7.10.0 they were
encoded as the string "0x". This change was not intentional, and it
resulted in invalid signatures.

This problem was introduced in `@metamask/eth-sig-util@6.0.1` (see here
for details: MetaMask/eth-sig-util#340). This
package was introduced to mobile when `@metamask/keyring-controller` was
updated to v6 (#7267).
The keyrings themselves still use `@metamask/eth-sig-util@5.0.1`, but
the `KeyringController` is signing these messages directly rather than
delegating to the keyrings, which is why the newer
`@metamask/eth-sig-util` package is used here.

This has been resolved by updating all affected versions of
`@metamask/eth-sig-util`.

## **Related issues**

Fixes #7792

## **Manual testing steps**

1. Navigate to https://gudahtt.github.io/test-dapp/ in the in-app
browser
2. Sign a message using `eth_signTypedData_v4` 
3. Attempt to verify that message. On production (v7.10.0) this does not
work. It should work correctly on this branch, returning the signing
account address.

## **Screenshots/Recordings**

**Before**

https://recordit.co/xejXpo4mlh

**After**

https://recordit.co/NnnpxbCVRB

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've clearly explained what problem this PR is solving and how it
is solved.
- [x] I've linked related issues
- [x] I've included manual testing steps
- [x] I've included screenshots/recordings if applicable
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [x] I’ve properly set the pull request status:
  - [x] In case it's not yet "ready for review", I've set it to "draft".
- [x] In case it's "ready for review", I've changed it from "draft" to
"non-draft".

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: legobt <6wbvkn0j@anonaddy.me>
@metamaskbot metamaskbot added the release-7.13.0 Issue or pull request that will be included in release 7.13.0 label Nov 29, 2023
@chrisleewilcox chrisleewilcox removed the regression-RC DEPRECATED: Please use "regresssion-RC-x.y.z" label instead label Nov 30, 2023
@metamaskbot metamaskbot added the regression-RC DEPRECATED: Please use "regresssion-RC-x.y.z" label instead label Nov 30, 2023
@gauthierpetetin gauthierpetetin removed the release-7.13.0 Issue or pull request that will be included in release 7.13.0 label Dec 5, 2023
@Gudahtt Gudahtt self-assigned this Dec 5, 2023
@DmitryBespalov
Copy link

Hey there, just to let you know that the fix above still didn't remove the issue in the most recent MetaMask app. We went with a workaround: using empty string "" instead of "0x" for a data/bytes parameter with the eth_signTypedData_v4.

@cieltan
Copy link
Author

cieltan commented Dec 21, 2023

Hey there, just to let you know that the fix above still didn't remove the issue in the most recent MetaMask app. We went with a workaround: using empty string "" instead of "0x" for a data/bytes parameter with the eth_signTypedData_v4.

It's unclear if this fix was even included in the 7.12.0 release? @Gudahtt for clarity if this fix is active in the app store version of the Metamask app?

@Gudahtt Gudahtt reopened this Dec 21, 2023
sethkfman pushed a commit that referenced this issue Dec 22, 2023
## **Description**

In v7.10.0, signatures including a `bytes` field with the value `0x`
were being encoded differently than before. Previously the string `0x`
was interpreted as an "empty" hex number, but as of v7.10.0 they were
encoded as the string "0x". This change was not intentional, and it
resulted in invalid signatures.

This problem was introduced in `@metamask/eth-sig-util@6.0.1` (see here
for details: MetaMask/eth-sig-util#340). This
package was introduced to mobile when `@metamask/keyring-controller` was
updated to v6 (#7267).
The keyrings themselves still use `@metamask/eth-sig-util@5.0.1`, but
the `KeyringController` is signing these messages directly rather than
delegating to the keyrings, which is why the newer
`@metamask/eth-sig-util` package is used here.

This has been resolved by updating all affected versions of
`@metamask/eth-sig-util`.

## **Related issues**

Fixes #7792

## **Manual testing steps**

1. Navigate to https://gudahtt.github.io/test-dapp/ in the in-app
browser
2. Sign a message using `eth_signTypedData_v4` 
3. Attempt to verify that message. On production (v7.10.0) this does not
work. It should work correctly on this branch, returning the signing
account address.

## **Screenshots/Recordings**

**Before**

https://recordit.co/xejXpo4mlh

**After**

https://recordit.co/NnnpxbCVRB

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've clearly explained what problem this PR is solving and how it
is solved.
- [x] I've linked related issues
- [x] I've included manual testing steps
- [x] I've included screenshots/recordings if applicable
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.
- [x] I’ve properly set the pull request status:
  - [x] In case it's not yet "ready for review", I've set it to "draft".
- [x] In case it's "ready for review", I've changed it from "draft" to
"non-draft".

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: legobt <6wbvkn0j@anonaddy.me>
@metamaskbot metamaskbot added the release-7.12.5 Issue or pull request that will be included in release 7.12.5 label Jan 3, 2024
@metamaskbot
Copy link
Collaborator

Missing release label release-7.12.5 on issue. Adding release label release-7.12.5 on issue, as issue is linked to PR #7886 which has this release label.

@Gudahtt
Copy link
Member

Gudahtt commented Jan 3, 2024

Sorry for the mix-up, this fix will be included in v7.12.5

@Gudahtt Gudahtt closed this as completed Jan 3, 2024
@Gudahtt Gudahtt removed the release-7.12.0 Issue or pull request that will be included in release 7.12.0 label Jan 3, 2024
muze-pus added a commit to muze-pus/test-dapp that referenced this issue Mar 8, 2024
The example `eth_signTypedData_v4` message has been updated to include
a field that can reproduce this bug: MetaMask/metamask-mobile#7792
That signing bug results in invalid signatures for any messages that
include a `bytes` field with the value `0x`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
external-contributor regression-prod-7.10.0 Regression bug that was found in production in release 7.10.0 regression-RC DEPRECATED: Please use "regresssion-RC-x.y.z" label instead regression-RC-7.12.5 release-7.12.5 Issue or pull request that will be included in release 7.12.5 Sev1-high An issue that may have caused fund loss or access to wallet in the past & may still be ongoing team-wallet-framework type-bug Something isn't working
Projects
None yet