A Curve user wanted to swap 5 Bitcoin for wBTC.

As Curve now supports native Bitcoin deposit routed through the renVM, the user deposit the Bitcoin and after six confirmations, Metamask prompted the user to confirm a transaction to mint renBTC and swap it to wBTC (via the Curve sbtc pool).

The Ledger device then showed the transaction on the device but when user clicked to accept it, the device then responded with an error 6985 (user cancelled).

Working with @btchip we discovered that in this case the transaction data was encoded using EIP-155 Simple replay attack protection which includes v, s, r (the three parts of a transaction signature).

When Ethereum Ledger app was created EIP 155 didn't exist and as a result, the app doesn't know when the transaction data ends as the three parts (v, s, r) can either be missing (pre EIP-155) or not (using EIP-155).

Communication with a Ledger happens in chunks because the communication buffer is limited. In this case, the user had an unlucky combination of derivation path and transaction data
and ended with a chunk that could look like the final part of a valid pre EIP 155 tx for the parser(right before the start of v, r, s). As a result, the parser thought it was signing a pre EIP-155 transaction while it was actually signing an EIP-155 transaction. The parser thinks data transmission is finished and returns an error on the v,r,s chunk of data which follows.

The user tried Ledger with Metamask, Ledger directly through Curve, 3 different ledgers Nano S devices as well as 2 OSes, MyCrypto and MyEtherWallet without success.

I managed to successfully resolve the issue, while @btchip was working on a fix, by getting the user to mint renBTC by using a recovery function in the contract which resulted in different transaction data which Ledger javascript library parsed correctly.

Ledger has now fixed the issue in their js library by checking if the transaction is EIP-155 or not to ensure this bug isn't accidentally reproduced.