From a5b81d85621aeda3cabafd316163f72c7a85833c Mon Sep 17 00:00:00 2001 From: amerkadicE <97883527+amerkadicE@users.noreply.github.com> Date: Fri, 18 Nov 2022 17:04:52 +0100 Subject: [PATCH] Fix message on sign typed data v4 screen (#16552) Co-authored-by: Frederik Bolding --- ui/helpers/utils/util.js | 58 ++++++++++++++++-------------- ui/helpers/utils/util.test.js | 67 +++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 26 deletions(-) diff --git a/ui/helpers/utils/util.js b/ui/helpers/utils/util.js index 924bc80d6..4f8ab2454 100644 --- a/ui/helpers/utils/util.js +++ b/ui/helpers/utils/util.js @@ -411,11 +411,37 @@ const solidityTypes = () => { ]; }; -export const sanitizeMessage = (msg, baseType, types) => { +const SOLIDITY_TYPES = solidityTypes(); + +const stripArrayType = (potentialArrayType) => + potentialArrayType.replace(/\[[[0-9]*\]*/gu, ''); + +const stripOneLayerofNesting = (potentialArrayType) => + potentialArrayType.replace(/\[[[0-9]*\]/u, ''); + +const isArrayType = (potentialArrayType) => + potentialArrayType.match(/\[[[0-9]*\]*/u) !== null; + +const isSolidityType = (type) => SOLIDITY_TYPES.includes(type); + +export const sanitizeMessage = (msg, primaryType, types) => { if (!types) { throw new Error(`Invalid types definition`); } + // Primary type can be an array. + const isArray = primaryType && isArrayType(primaryType); + if (isArray) { + return msg.map((value) => + sanitizeMessage(value, stripOneLayerofNesting(primaryType), types), + ); + } else if (isSolidityType(primaryType)) { + return msg; + } + + // If not, assume to be struct + const baseType = isArray ? stripArrayType(primaryType) : primaryType; + const baseTypeDefinitions = types[baseType]; if (!baseTypeDefinitions) { throw new Error(`Invalid primary type definition`); @@ -432,31 +458,11 @@ export const sanitizeMessage = (msg, baseType, types) => { return; } - // key has a type. check if the definedType is also a type - const nestedType = definedType.type.replace(/\[\]$/u, ''); - const nestedTypeDefinition = types[nestedType]; - - if (nestedTypeDefinition) { - if (definedType.type.endsWith('[]') > 0) { - // nested array - sanitizedMessage[msgKey] = msg[msgKey].map((value) => - sanitizeMessage(value, nestedType, types), - ); - } else { - // nested object - sanitizedMessage[msgKey] = sanitizeMessage( - msg[msgKey], - definedType.type, - types, - ); - } - } else { - // check if it's a valid solidity type - const isSolidityType = solidityTypes().includes(nestedType); - if (isSolidityType) { - sanitizedMessage[msgKey] = msg[msgKey]; - } - } + sanitizedMessage[msgKey] = sanitizeMessage( + msg[msgKey], + definedType.type, + types, + ); }); return sanitizedMessage; }; diff --git a/ui/helpers/utils/util.test.js b/ui/helpers/utils/util.test.js index 51893f783..d5ffabc0d 100644 --- a/ui/helpers/utils/util.test.js +++ b/ui/helpers/utils/util.test.js @@ -365,6 +365,10 @@ describe('util', () => { ], }, ], + nestArray: [ + [12, 34, 56], + [56, 78, 89], + ], }; primaryType = 'Mail'; types = { @@ -378,6 +382,8 @@ describe('util', () => { { name: 'from', type: 'Person' }, { name: 'to', type: 'Person[]' }, { name: 'contents', type: 'string' }, + { name: 'nestArray', type: 'uint256[2][2]' }, + { name: 'nestedPeople', type: 'Person[][]' }, ], Person: [ { name: 'name', type: 'string' }, @@ -408,6 +414,67 @@ describe('util', () => { expect(result.to[0].wallets).toHaveLength(3); }); + it('should return parsed nested array if defined', () => { + const result = util.sanitizeMessage( + { + nestArray: [ + [12, 34, 56], + [56, 78, 89], + ], + }, + primaryType, + types, + ); + expect(result.nestArray).toHaveLength(2); + expect(result.nestArray[0]).toHaveLength(3); + expect(result.nestArray[0][0]).toStrictEqual(12); + expect(result.nestArray[0][2]).toStrictEqual(56); + }); + + it('should return parsed nested array with struct if defined', () => { + const msg = { + nestedPeople: [ + [ + { + name: 'Bob', + wallets: [ + '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57', + '0xB0B0b0b0b0b0B000000000000000000000000000', + ], + }, + ], + [ + { + name: 'Ben', + wallets: [ + '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57', + '0xB0B0b0b0b0b0B000000000000000000000000000', + ], + }, + { + name: 'Brandon', + wallets: [ + '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + '0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57', + '0xB0B0b0b0b0b0B000000000000000000000000000', + ], + }, + ], + ], + }; + const result = util.sanitizeMessage(msg, primaryType, types); + expect(result.nestedPeople).toHaveLength(2); + expect(result.nestedPeople[0]).toHaveLength(1); + expect(result.nestedPeople[0][0].name).toStrictEqual('Bob'); + expect(result.nestedPeople[0][0].wallets).toHaveLength(3); + expect(result.nestedPeople[0][0].wallets[0]).toStrictEqual( + '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB', + ); + expect(result.nestedPeople[1][1].name).toStrictEqual('Brandon'); + }); + it('should return ignore message data with unknown types', () => { message.do_not_display = 'one'; message.do_not_display_2 = {