From 5b324ae1e4b5fd4d1a21e935ceeeca1e3e5bff29 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 27 Jun 2024 09:43:47 -0230 Subject: [PATCH] fix: Fix BaseControllerV1 state rehydration (#10133) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## **Description** We were failing to properly restore persisted state for some BaseControllerV1 controllers. This resulted in state being lost when the application was restarted. The only confirmed affected controller so far is the `NftController`. The context here is that for some older controllers, rather than passing the initial state into the controller directly when it is constructed, we call the `update` function directly. This has always been a bad practice (controllers should update their own state), and we're forced to fix this for controllers that we update to `BaseControllerV2` (because directly updating state like this is no longer possible. But this method of rehydrating controller state was still relied upon in some cases. This was broken recently in #9570 when a condition was added to fix a type error. The condition was meant to check that the controller had a `subscribe` function. Unfortunately this `hasProperty` check only looks at owned properties, not inherited properties, and the `subscribe` function was inherited from the base class. It has been updated to use the `in` operator instead, which does look up the entire prototype chain. ## **Related issues** Fixes #10057 ## **Manual testing steps** See #10057 ## **Screenshots/Recordings** ### **Before** See #10057 ### **After** https://github.com/MetaMask/metamask-mobile/assets/2459287/b7cf3e09-086b-4964-8180-e58195969e17 ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [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. ## **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. --- app/core/Engine.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/core/Engine.ts b/app/core/Engine.ts index e18dcc6486d..42f3030c9b8 100644 --- a/app/core/Engine.ts +++ b/app/core/Engine.ts @@ -1439,7 +1439,8 @@ class Engine { for (const controller of controllers) { if ( hasProperty(initialState, controller.name) && - hasProperty(controller, 'subscribe') && + // Use `in` operator here because the `subscribe` function is one level up the prototype chain + 'subscribe' in controller && controller.subscribe !== undefined ) { // The following type error can be addressed by passing initial state into controller constructors instead