From 7906f181049f8578b768299ad40672e84189883e Mon Sep 17 00:00:00 2001 From: Jyoti Puri Date: Tue, 5 Sep 2023 15:43:43 +0530 Subject: [PATCH] Blockaid validation should be done on ethereum mainnet only (#20709) --- app/scripts/lib/ppom/ppom-middleware.test.ts | 146 ++++++++----------- app/scripts/lib/ppom/ppom-middleware.ts | 11 +- app/scripts/metamask-controller.js | 6 +- 3 files changed, 75 insertions(+), 88 deletions(-) diff --git a/app/scripts/lib/ppom/ppom-middleware.test.ts b/app/scripts/lib/ppom/ppom-middleware.test.ts index 8276f8361..34e1952cc 100644 --- a/app/scripts/lib/ppom/ppom-middleware.test.ts +++ b/app/scripts/lib/ppom/ppom-middleware.test.ts @@ -1,3 +1,4 @@ +import { CHAIN_IDS } from '../../../../shared/constants/network'; import { BlockaidReason, BlockaidResultType, @@ -14,38 +15,48 @@ Object.defineProperty(globalThis, 'performance', { value: () => undefined, }); +const createMiddleWare = ( + usePPOM?: any, + securityAlertsEnabled?: boolean, + chainId?: string, +) => { + const usePPOMMock = jest.fn(); + const ppomController = { + usePPOM: usePPOM || usePPOMMock, + }; + const preferenceController = { + store: { + getState: () => ({ + securityAlertsEnabled: + securityAlertsEnabled === undefined ?? securityAlertsEnabled, + }), + }, + }; + const networkController = { + state: { providerConfig: { chainId: chainId || CHAIN_IDS.MAINNET } }, + }; + return createPPOMMiddleware( + ppomController as any, + preferenceController as any, + networkController as any, + ); +}; + describe('PPOMMiddleware', () => { it('should call ppomController.usePPOM for requests of type confirmation', async () => { - const useMock = jest.fn(); - const ppomController = { - usePPOM: useMock, - }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: true }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + const usePPOMMock = jest.fn(); + const middlewareFunction = createMiddleWare(usePPOMMock); await middlewareFunction( { method: 'eth_sendTransaction' }, undefined, () => undefined, ); - expect(useMock).toHaveBeenCalledTimes(1); + expect(usePPOMMock).toHaveBeenCalledTimes(1); }); it('should add validation response on confirmation requests', async () => { - const ppomController = { - usePPOM: async () => Promise.resolve('VALIDATION_RESULT'), - }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: true }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + const usePPOM = async () => Promise.resolve('VALIDATION_RESULT'); + const middlewareFunction = createMiddleWare(usePPOM); const req = { method: 'eth_sendTransaction', securityAlertResponse: undefined, @@ -55,16 +66,19 @@ describe('PPOMMiddleware', () => { }); it('should not do validation if user has not enabled preference', async () => { - const ppomController = { - usePPOM: async () => Promise.resolve('VALIDATION_RESULT'), + const usePPOM = async () => Promise.resolve('VALIDATION_RESULT'); + const middlewareFunction = createMiddleWare(usePPOM, false); + const req = { + method: 'eth_sendTransaction', + securityAlertResponse: undefined, }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: false }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + await middlewareFunction(req, undefined, () => undefined); + expect(req.securityAlertResponse).toBeUndefined(); + }); + + it('should not do validation if user is not on mainnet', async () => { + const usePPOM = async () => Promise.resolve('VALIDATION_RESULT'); + const middlewareFunction = createMiddleWare(usePPOM, false, '0x2'); const req = { method: 'eth_sendTransaction', securityAlertResponse: undefined, @@ -74,18 +88,10 @@ describe('PPOMMiddleware', () => { }); it('should set Failed type in response if usePPOM throw error', async () => { - const ppomController = { - usePPOM: async () => { - throw new Error('some error'); - }, + const usePPOM = async () => { + throw new Error('some error'); }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: true }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + const middlewareFunction = createMiddleWare(usePPOM); const req = { method: 'eth_sendTransaction', securityAlertResponse: undefined, @@ -103,18 +109,10 @@ describe('PPOMMiddleware', () => { const ppom = { validateJsonRpc: () => undefined, }; - const ppomController = { - usePPOM: async (callback: any) => { - callback(ppom); - }, + const usePPOM = async (callback: any) => { + callback(ppom); }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: true }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + const middlewareFunction = createMiddleWare(usePPOM); const nextMock = jest.fn(); await middlewareFunction( { method: 'eth_sendTransaction' }, @@ -125,18 +123,10 @@ describe('PPOMMiddleware', () => { }); it('should call next method when ppomController.usePPOM throws error', async () => { - const ppomController = { - usePPOM: async (_callback: any) => { - throw Error('Some error'); - }, + const usePPOM = async (_callback: any) => { + throw Error('Some error'); }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: true }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + const middlewareFunction = createMiddleWare(usePPOM); const nextMock = jest.fn(); await middlewareFunction( { method: 'eth_sendTransaction' }, @@ -151,18 +141,10 @@ describe('PPOMMiddleware', () => { const ppom = { validateJsonRpc: validateMock, }; - const ppomController = { - usePPOM: async (callback: any) => { - callback(ppom); - }, + const usePPOM = async (callback: any) => { + callback(ppom); }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: true }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + const middlewareFunction = createMiddleWare(usePPOM); await middlewareFunction( { method: 'eth_sendTransaction' }, undefined, @@ -176,18 +158,10 @@ describe('PPOMMiddleware', () => { const ppom = { validateJsonRpc: validateMock, }; - const ppomController = { - usePPOM: async (callback: any) => { - callback(ppom); - }, + const usePPOM = async (callback: any) => { + callback(ppom); }; - const preferenceController = { - store: { getState: () => ({ securityAlertsEnabled: true }) }, - }; - const middlewareFunction = createPPOMMiddleware( - ppomController as any, - preferenceController as any, - ); + const middlewareFunction = createMiddleWare(usePPOM); await middlewareFunction( { method: 'eth_someRequest' }, undefined, diff --git a/app/scripts/lib/ppom/ppom-middleware.ts b/app/scripts/lib/ppom/ppom-middleware.ts index 201187966..5dc027bf5 100644 --- a/app/scripts/lib/ppom/ppom-middleware.ts +++ b/app/scripts/lib/ppom/ppom-middleware.ts @@ -1,10 +1,12 @@ import { PPOM } from '@blockaid/ppom_release'; import { PPOMController } from '@metamask/ppom-validator'; +import { NetworkController } from '@metamask/network-controller'; import { BlockaidReason, BlockaidResultType, } from '../../../../shared/constants/security-provider'; +import { CHAIN_IDS } from '../../../../shared/constants/network'; import PreferencesController from '../../controllers/preferences'; const { sentry } = global as any; @@ -31,17 +33,24 @@ const ConfirmationMethods = Object.freeze([ * * @param ppomController - Instance of PPOMController. * @param preferencesController - Instance of PreferenceController. + * @param networkController - Instance of NetworkController. * @returns PPOMMiddleware function. */ export function createPPOMMiddleware( ppomController: PPOMController, preferencesController: PreferencesController, + networkController: NetworkController, ) { return async (req: any, _res: any, next: () => void) => { try { const securityAlertsEnabled = preferencesController.store.getState()?.securityAlertsEnabled; - if (securityAlertsEnabled && ConfirmationMethods.includes(req.method)) { + const { chainId } = networkController.state.providerConfig; + if ( + securityAlertsEnabled && + ConfirmationMethods.includes(req.method) && + chainId === CHAIN_IDS.MAINNET + ) { // eslint-disable-next-line require-atomic-updates req.securityAlertResponse = await ppomController.usePPOM( async (ppom: PPOM) => { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 19a7bd5b7..52fc263aa 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -4076,7 +4076,11 @@ export default class MetamaskController extends EventEmitter { ///: BEGIN:ONLY_INCLUDE_IN(blockaid) engine.push( - createPPOMMiddleware(this.ppomController, this.preferencesController), + createPPOMMiddleware( + this.ppomController, + this.preferencesController, + this.networkController, + ), ); ///: END:ONLY_INCLUDE_IN