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

fix: isPermitSignatureRequest logic. Do not display as Permit if spender is not present #27384

Closed
wants to merge 9 commits into from
61 changes: 60 additions & 1 deletion test/data/confirmations/typed_sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,65 @@ export const orderSignatureMsg = {
},
};

export const permitMessageDataJson = {
types: {
EIP712Domain: [
{
name: 'name',
type: 'string',
},
{
name: 'version',
type: 'string',
},
{
name: 'chainId',
type: 'uint256',
},
{
name: 'verifyingContract',
type: 'address',
},
],
Permit: [
{
name: 'owner',
type: 'address',
},
{
name: 'spender',
type: 'address',
},
{
name: 'value',
type: 'uint256',
},
{
name: 'nonce',
type: 'uint256',
},
{
name: 'deadline',
type: 'uint256',
},
],
},
primaryType: 'Permit',
domain: {
name: 'MyToken',
version: '1',
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
chainId: 1,
},
message: {
owner: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
spender: '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4',
value: 3000,
nonce: 0,
deadline: 50000000000,
},
};

export const permitSignatureMsg = {
id: '0b1787a0-1c44-11ef-b70d-e7064bd7b659',
securityAlertResponse: {
Expand All @@ -174,7 +233,7 @@ export const permitSignatureMsg = {
time: 1716826404122,
type: TransactionType.signTypedData,
msgParams: {
data: '{"types":{"EIP712Domain":[{"name":"name","type":"string"},{"name":"version","type":"string"},{"name":"chainId","type":"uint256"},{"name":"verifyingContract","type":"address"}],"Permit":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"nonce","type":"uint256"},{"name":"deadline","type":"uint256"}]},"primaryType":"Permit","domain":{"name":"MyToken","version":"1","verifyingContract":"0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC","chainId":1},"message":{"owner":"0x935e73edb9ff52e23bac7f7e043a1ecd06d05477","spender":"0x5B38Da6a701c568545dCfcB03FcB875f56beddC4","value":3000,"nonce":0,"deadline":50000000000}}',
data: JSON.stringify(permitMessageDataJson),
from: '0x935e73edb9ff52e23bac7f7e043a1ecd06d05477',
version: 'V4',
requestId: 14,
Expand Down
18 changes: 18 additions & 0 deletions ui/pages/confirmations/utils/confirm.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { ApprovalRequest } from '@metamask/approval-controller';
import { ApprovalType } from '@metamask/controller-utils';
import { TransactionType } from '@metamask/transaction-controller';
import { cloneDeep } from 'lodash';

import {
orderSignatureMsg,
permitMessageDataJson,
permitSignatureMsg,
unapprovedTypedSignMsgV4,
} from '../../../../test/data/confirmations/typed_sign';
Expand Down Expand Up @@ -76,6 +78,22 @@ describe('confirm util', () => {
);
expect(result).toStrictEqual(true);
});

it('returns false if it is missing a valid spender address', () => {
const data = cloneDeep(permitMessageDataJson);
data.message.spender = '';

const mockMessage = {
...permitSignatureMsg,
msgParams: {
data: JSON.stringify(data),
},
} as SignatureRequestType;

const result = isPermitSignatureRequest(mockMessage);
expect(result).toStrictEqual(false);
});

it('returns false for request not of type permit signature', () => {
const result = isPermitSignatureRequest(
unapprovedTypedSignMsgV4 as SignatureRequestType,
Expand Down
18 changes: 15 additions & 3 deletions ui/pages/confirmations/utils/confirm.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ApprovalRequest } from '@metamask/approval-controller';
import { ApprovalType } from '@metamask/controller-utils';
import { TransactionType } from '@metamask/transaction-controller';
import { Json } from '@metamask/utils';
import { isHexString, Json } from '@metamask/utils';
import {
PRIMARY_TYPES_ORDER,
PRIMARY_TYPES_PERMIT,
Expand Down Expand Up @@ -77,7 +77,11 @@ export const isOrderSignatureRequest = (request: SignatureRequestType) => {
};

/**
* Returns true if the request is a Permit Typed Sign signature request
* Returns true if the request appears to be an EIP-2612 Permit or Permit2 signTypedData signature request.
* Caution: This is a limited check. It may include other Permits which are not the specific types mentioned
* if they match the primaryType check and have a spender field.
*
* TODO: Improve detection of fields.
*
* @param request - The confirmation request to check
*/
Expand All @@ -91,10 +95,18 @@ export const isPermitSignatureRequest = (request?: Confirmation) => {
) {
return false;
}
const { primaryType } = parseTypedDataMessage(

const {
message: { spender },
primaryType,
} = parseTypedDataMessage(
(request as SignatureRequestType).msgParams?.data as string,
);

if (!isHexString(spender)) {
return false;
}

return PRIMARY_TYPES_PERMIT.includes(primaryType);
};

Expand Down
Loading