Closed cgrellard-ledger closed 1 year ago
We will need to merge Sentry PR with this one to being able to monitor the fix.
Currently Sentry doesn't work properly. Due to Authentication, I'm not able to track in "production" mode just locally @KVNLS
This PR fixes the issue that was causing some swap transactions to lose their
data
field resulting in users losing fundsIntroduced on June 30 2023 by this commit (here is the JIRA ticket)
๐๏ธ Reasons for the pendingFlow
When we are connected to a dapp (paraswap for example) and we trigger an operation (either a sign message or a transaction) some dapp send the information of the operation to the wallet connect live app that then triggers the appropriate flow on Ledger Live. However some dapp also triggers a deeplink that opens Ledger Live and redirects to the live app which causes it to refresh and it reinitializes the transport layer of the wallet api client. When this occurs and a flow (either sign message or signAndBroadcast transaction) was already opened then the live app will never get the result of the flow once it is either rejected or finished successfully (this issue was initially reported by opensea) On the following screen record we can see that once I trigger a swap from paraswap the flow opens up in ledger live directly but when the deeplink is then triggered (either manually when I click on
Open Ledger Live
or automatically if I had previously clicked on the checkbox above) then the live app is refreshed behind the sign transaction flow which resets the transport between Ledger Live and the live app Screen record : https://github.com/LedgerHQ/wallet-connect-live-app/assets/17146928/7f0d1a6b-f9ab-4237-a112-f91c7eb94a36 The pendingFlow stores the data of an ongoing operation (sign message or sign and broadcast transaction) and triggers the appropriate flow on Ledger Live with those data when the live app refreshes and a new transport layer has been initialized so that the live app can get the response of this flow once it's finished and send the result to the dapp which fixes the issue of this ticket๐ Explanation of the swap transaction critical bug
This bug occurred when triggering a pending flow to send a tx to Ledger Live when the live app was refreshed by a deeplink. We fetched the tx from the localStorage before sending it to ledger live but the data field being a
Buffer
its type was modified (from a Buffer to an Object) when being stored by zustand in the localStorage. So when we were getting it back at the start of the live app and sent it to Ledger Live this field was not a Buffer anymore but an object and when Ledger Live converted it to a string it resulted in the data being emptyThe consequence of that is the transaction being executed as a simple send to the dapp contract address instead of a swap (thus the users losing funds)
โ Solution
Save the
ethTx
object (which has a type ofEthTransaction
and is only composed of strings) in the localStorage instead of theliveTx
object (which has a type ofEthereumTransaction
and is composed of strings, BigNumbers and a Buffer). Then converting theethTx
to aliveTx
just before sending the transaction to Ledger LiveThat avoids any type modification and the data is still intact when converting the
EthTransaction
to aEthereumTransaction
๐ How to reproduce the bug
0b86a4c1000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000038d7ea4c680000000000000000000000000000000000000000000000000001a7afc8d23253b92000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000004de5c3d03e4f041fd4cd388c549ee2a29a9e5075882f
)Open Ledger Live
in the modal on your browser[object Object]
which is why it is updated to0x
in Ledger Live when casting itScreen record : https://github.com/LedgerHQ/wallet-connect-live-app/assets/17146928/a9588dd7-964d-4e7c-8b59-14d62beb6df5
๐งช Testing the fix
Open Ledger Live
in the modal on your browserScreen record : https://github.com/LedgerHQ/wallet-connect-live-app/assets/17146928/45469a42-7ea1-4231-ab93-6521376928af
๐ฌ How could this have been avoided
The pendingFlow has been carefully tested manually by both the devs and the QA but this issue only happened when executing specific steps in the right order and was only visible for transactions carrying some data (such as swaps) and these were not part of the manual testing plan of the pendingFlow. However it would have been caught before reaching production if we had developed proper automated tests for the pendingFlow during the development phase and it could definitely have been avoided.
๐ต๏ธ How can we improve the investigation
More detailed logs on both the Live App and Ledger Live would have helped us identify which part was at the cause of the issue and it would have reduced the number of teams and people involved in the investigation. Also some tests on all the potential sources of the issue (live app, wallet api, ledger live, ...) where we could have sent the exact data of the transaction that had the issue could have eliminated some of them and saved us some resources as well as direct our focus to the remaining potential sources.
๐ฎ What can we do to avoid that in the future
Now that the fix has been implemented and released, it shouldn't be possible anymore for the data field of a transaction to be erased by the pendingFlow. We also added a double security check to throw an error and not execute the
signAndBroadcast
method if the data field were to be erased at some point in the live app. In addition, the automated test covering this particular issue is currently in development and we are actively working on defining the whole testing strategy to cover the wallet connect live app and putting in place all the tools that are needed to properly test it. The automated tests will now be part of the definition of done of the upcoming features and bugfixes that will be implemented.