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]: App freezes for 1 minute then crash when swapping unapproved token #11085

Closed
davibroc opened this issue Sep 6, 2024 · 2 comments · Fixed by #11165
Closed

[Bug]: App freezes for 1 minute then crash when swapping unapproved token #11085

davibroc opened this issue Sep 6, 2024 · 2 comments · Fixed by #11165
Assignees
Labels
regression-prod-7.29.0 Regression bug that was found in production in release 7.29.0 release-7.31.0 Issue or pull request that will be included in release 7.31.0 release-7.32.0 Issue or pull request that will be included in release 7.32.0 release-blocker This bug is blocking the next release team-confirmations Push issues to confirmations team type-bug Something isn't working

Comments

@davibroc
Copy link
Contributor

davibroc commented Sep 6, 2024

Describe the bug

After an app install or app upgrade, or after an account import, if I swap an unapproved token the app will hang and crash after 1 minute.

It started happening with RC 7.27.1 after the TransactionController jumps from v13 to v35 with this commit
#10263

If I build the app with the following previous commit it doesn't repro
#10458

Watch video

Hang2.mov

Expected behavior

The Swap completes successfully

Screenshots/Recordings

No response

Steps to reproduce

  1. Install the app from scratch on the Android or iOS emulator
  2. Import an account with funds, you can use a Tenderly fork to save money
  3. Swap ETH->Unapproved token
  4. Swap Unapproved token->ETH

Notice the app freezing and then crashing after 1 minute

Error messages or log output

No response

Detection stage

During 7.30.0 release testing

Version

7.27.1 and older

Build type

None

Device

iPhone 12 Pro

Operating system

iOS

Additional context

No response

Severity

No response

@davibroc davibroc added type-bug Something isn't working release-blocker This bug is blocking the next release team-transactions Transactions team release-7.31.0 Issue or pull request that will be included in release 7.31.0 labels Sep 6, 2024
@github-project-automation github-project-automation bot moved this to To be fixed in Bugs by severity Sep 6, 2024
@sethkfman sethkfman added the regression-prod-7.29.0 Regression bug that was found in production in release 7.29.0 label Sep 6, 2024
@infiniteflower
Copy link
Contributor

infiniteflower commented Sep 6, 2024

I was able to reproduce on iOS simulator on release/7.27.0

release/7.26.0 seems ok

Between Mobile 7.26.0 and 7.27.0, TransactionController jumps from v13 to v35
The app freezes on TransactionController.addTransaction

@davibroc
Copy link
Contributor Author

davibroc commented Sep 8, 2024

@infiniteflower I confirm that this started happening after the TransactionController jumps from v13 to v35 with this commit #10263

If I build the app with previous the following previous commit it doesn't repro
#10458

@matthewwalsh0 matthewwalsh0 added team-confirmations Push issues to confirmations team and removed team-transactions Transactions team labels Sep 10, 2024
@matthewwalsh0 matthewwalsh0 self-assigned this Sep 11, 2024
sethkfman added a commit that referenced this issue Sep 13, 2024
## **Description**

The freeze was ultimately caused by a render loop inside
`RootRPCMethodsUI` caused by the
`TransactionController:unapprovedTransactionAdded` listener.

More specifically:

1. When swaps are detected, the transaction is automatically approved
via the `autoSign` function.
2. This registers a listener to send a completed metric once the
transaction is confirmed.
3. This is triggered by adding the transaction ID to a queue via the
`addTransactionMetaIdForListening` function.
4. This function updates React state, but was also using that same state
as a dependency, meaning the callback was updated on every usage.
5. This function was a dependency of `autoSign` which was in turn a
dependency of `onUnapprovedTransaction` which was the only dependency
for a `useEffect` that re-created the
`TransactionController:unapprovedTransactionAdded` listener.
6. The `ControllerMessenger` processes listeners using an iterator
rather than a static list meaning each new listener was automatically
ran which in turn created another listener and resulted in a very high
CPU render loop.

The core fix was to update the `addTransactionMetaIdForListening` to
update the state using the callback override meaning it did not require
the state dependency.

However during testing it was discovered that this swaps completed
metric was not functioning since the `swapsTransaction` state was being
incorrectly populated with the `TransactionController` instance due to a
legacy function argument that was not fully removed.

This has been addressed, and all swaps transactions updates have been
abstracted via a new `swaps-transactions` utility file.

## **Related issues**

Fixes:
[#11085](#11085)

## **Manual testing steps**

Full swaps regression, including:

- Swaps with approvals.
- Smart swaps.
- Metric support.
- Multiple sequential swaps (with and without approvals).

## **Screenshots/Recordings**

### **Before**

### **After**

## **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.

---------

Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
@github-project-automation github-project-automation bot moved this from To be fixed to Fixed in Bugs by severity Sep 13, 2024
runway-github bot added a commit that referenced this issue Sep 13, 2024
## **Description**

The freeze was ultimately caused by a render loop inside
`RootRPCMethodsUI` caused by the
`TransactionController:unapprovedTransactionAdded` listener.

More specifically:

1. When swaps are detected, the transaction is automatically approved
via the `autoSign` function.
2. This registers a listener to send a completed metric once the
transaction is confirmed.
3. This is triggered by adding the transaction ID to a queue via the
`addTransactionMetaIdForListening` function.
4. This function updates React state, but was also using that same state
as a dependency, meaning the callback was updated on every usage.
5. This function was a dependency of `autoSign` which was in turn a
dependency of `onUnapprovedTransaction` which was the only dependency
for a `useEffect` that re-created the
`TransactionController:unapprovedTransactionAdded` listener.
6. The `ControllerMessenger` processes listeners using an iterator
rather than a static list meaning each new listener was automatically
ran which in turn created another listener and resulted in a very high
CPU render loop.

The core fix was to update the `addTransactionMetaIdForListening` to
update the state using the callback override meaning it did not require
the state dependency.

However during testing it was discovered that this swaps completed
metric was not functioning since the `swapsTransaction` state was being
incorrectly populated with the `TransactionController` instance due to a
legacy function argument that was not fully removed.

This has been addressed, and all swaps transactions updates have been
abstracted via a new `swaps-transactions` utility file.

## **Related issues**

Fixes:
[#11085](#11085)

## **Manual testing steps**

Full swaps regression, including:

- Swaps with approvals.
- Smart swaps.
- Metric support.
- Multiple sequential swaps (with and without approvals).

## **Screenshots/Recordings**

### **Before**

### **After**

## **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.

---------

Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
runway-github bot added a commit that referenced this issue Sep 13, 2024
## **Description**

The freeze was ultimately caused by a render loop inside
`RootRPCMethodsUI` caused by the
`TransactionController:unapprovedTransactionAdded` listener.

More specifically:

1. When swaps are detected, the transaction is automatically approved
via the `autoSign` function.
2. This registers a listener to send a completed metric once the
transaction is confirmed.
3. This is triggered by adding the transaction ID to a queue via the
`addTransactionMetaIdForListening` function.
4. This function updates React state, but was also using that same state
as a dependency, meaning the callback was updated on every usage.
5. This function was a dependency of `autoSign` which was in turn a
dependency of `onUnapprovedTransaction` which was the only dependency
for a `useEffect` that re-created the
`TransactionController:unapprovedTransactionAdded` listener.
6. The `ControllerMessenger` processes listeners using an iterator
rather than a static list meaning each new listener was automatically
ran which in turn created another listener and resulted in a very high
CPU render loop.

The core fix was to update the `addTransactionMetaIdForListening` to
update the state using the callback override meaning it did not require
the state dependency.

However during testing it was discovered that this swaps completed
metric was not functioning since the `swapsTransaction` state was being
incorrectly populated with the `TransactionController` instance due to a
legacy function argument that was not fully removed.

This has been addressed, and all swaps transactions updates have been
abstracted via a new `swaps-transactions` utility file.

## **Related issues**

Fixes:
[#11085](#11085)

## **Manual testing steps**

Full swaps regression, including:

- Swaps with approvals.
- Smart swaps.
- Metric support.
- Multiple sequential swaps (with and without approvals).

## **Screenshots/Recordings**

### **Before**

### **After**

## **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.

---------

Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
runway-github bot pushed a commit that referenced this issue Sep 13, 2024
)

## **Description**

The freeze was ultimately caused by a render loop inside
`RootRPCMethodsUI` caused by the
`TransactionController:unapprovedTransactionAdded` listener.

More specifically:

1. When swaps are detected, the transaction is automatically approved
via the `autoSign` function.
2. This registers a listener to send a completed metric once the
transaction is confirmed.
3. This is triggered by adding the transaction ID to a queue via the
`addTransactionMetaIdForListening` function.
4. This function updates React state, but was also using that same state
as a dependency, meaning the callback was updated on every usage.
5. This function was a dependency of `autoSign` which was in turn a
dependency of `onUnapprovedTransaction` which was the only dependency
for a `useEffect` that re-created the
`TransactionController:unapprovedTransactionAdded` listener.
6. The `ControllerMessenger` processes listeners using an iterator
rather than a static list meaning each new listener was automatically
ran which in turn created another listener and resulted in a very high
CPU render loop.

The core fix was to update the `addTransactionMetaIdForListening` to
update the state using the callback override meaning it did not require
the state dependency.

However during testing it was discovered that this swaps completed
metric was not functioning since the `swapsTransaction` state was being
incorrectly populated with the `TransactionController` instance due to a
legacy function argument that was not fully removed.

This has been addressed, and all swaps transactions updates have been
abstracted via a new `swaps-transactions` utility file.

## **Related issues**

Fixes:
[#11085](#11085)

## **Manual testing steps**

Full swaps regression, including:

- Swaps with approvals.
- Smart swaps.
- Metric support.
- Multiple sequential swaps (with and without approvals).

## **Screenshots/Recordings**

### **Before**

### **After**

## **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.

---------

Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
@metamaskbot metamaskbot added the release-7.32.0 Issue or pull request that will be included in release 7.32.0 label Sep 13, 2024
sethkfman added a commit that referenced this issue Sep 13, 2024
)

- fix: freeze during swap with approval (#11165)

## **Description**

The freeze was ultimately caused by a render loop inside
`RootRPCMethodsUI` caused by the
`TransactionController:unapprovedTransactionAdded` listener.

More specifically:

1. When swaps are detected, the transaction is automatically approved
via the `autoSign` function.
2. This registers a listener to send a completed metric once the
transaction is confirmed.
3. This is triggered by adding the transaction ID to a queue via the
`addTransactionMetaIdForListening` function.
4. This function updates React state, but was also using that same state
as a dependency, meaning the callback was updated on every usage.
5. This function was a dependency of `autoSign` which was in turn a
dependency of `onUnapprovedTransaction` which was the only dependency
for a `useEffect` that re-created the
`TransactionController:unapprovedTransactionAdded` listener.
6. The `ControllerMessenger` processes listeners using an iterator
rather than a static list meaning each new listener was automatically
ran which in turn created another listener and resulted in a very high
CPU render loop.

The core fix was to update the `addTransactionMetaIdForListening` to
update the state using the callback override meaning it did not require
the state dependency.

However during testing it was discovered that this swaps completed
metric was not functioning since the `swapsTransaction` state was being
incorrectly populated with the `TransactionController` instance due to a
legacy function argument that was not fully removed.

This has been addressed, and all swaps transactions updates have been
abstracted via a new `swaps-transactions` utility file.

## **Related issues**

Fixes:
[#11085](#11085)

## **Manual testing steps**

Full swaps regression, including:

- Swaps with approvals.
- Smart swaps.
- Metric support.
- Multiple sequential swaps (with and without approvals).

## **Screenshots/Recordings**

### **Before**

### **After**

## **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.

---------

Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
[059a391](059a391)

---------

Co-authored-by: Matthew Walsh <matthew.walsh@consensys.net>
Co-authored-by: sethkfman <10342624+sethkfman@users.noreply.github.com>
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
regression-prod-7.29.0 Regression bug that was found in production in release 7.29.0 release-7.31.0 Issue or pull request that will be included in release 7.31.0 release-7.32.0 Issue or pull request that will be included in release 7.32.0 release-blocker This bug is blocking the next release team-confirmations Push issues to confirmations team type-bug Something isn't working
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

5 participants