Skip to content

Commit b89a3ea

Browse files
1.35.2-0.0.2: [fix] Fix ledger signing for EIP1559 (#729)
1 parent 3e038c9 commit b89a3ea

File tree

3 files changed

+396
-153
lines changed

3 files changed

+396
-153
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bnc-onboard",
3-
"version": "1.35.2-0.0.1",
3+
"version": "1.35.2-0.0.2",
44
"description": "Onboard users to web3 by allowing them to select a wallet, get that wallet ready to transact and have access to synced wallet state.",
55
"keywords": [
66
"ethereum",

src/modules/select/wallets/ledger.ts

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,10 @@ async function ledgerProvider(options: LedgerProviderOptions) {
8686
const { generateAddresses, isValidPath } = await import('./hd-wallet')
8787
const { default: Eth } = await import('@ledgerhq/hw-app-eth')
8888

89-
const { Transaction } = await import('@ethereumjs/tx')
90-
const { default: Common } = await import('@ethereumjs/common')
89+
const { TransactionFactory: Transaction, Capability } = await import(
90+
'@ethereumjs/tx'
91+
)
92+
const { default: Common, Hardfork } = await import('@ethereumjs/common')
9193
const ethUtil = await import('ethereumjs-util')
9294
const { TypedDataUtils } = await import('eth-sig-util')
9395

@@ -403,38 +405,47 @@ async function ledgerProvider(options: LedgerProviderOptions) {
403405

404406
async function signTransaction(transactionData: any) {
405407
const path = [...addressToPath.values()][0]
406-
const { BN, toBuffer } = ethUtil
408+
const { rlp } = ethUtil
407409
const common = new Common({
408-
chain: customNetwork || networkName(networkId)
410+
chain: customNetwork || networkName(networkId),
411+
// Berlin is the minimum hardfork that will allow for EIP1559
412+
hardfork: Hardfork.Berlin,
413+
// List of supported EIPS
414+
eips: [1559]
409415
})
410416
try {
417+
// The below implemenation is adapted from:
418+
// https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/tx#signing-with-a-hardware-or-external-wallet
419+
transactionData.gasLimit = transactionData.gas ?? transactionData.gasLimit
411420
const transaction = Transaction.fromTxData(
412421
{
413-
...transactionData,
414-
gasLimit: transactionData.gas ?? transactionData.gasLimit
422+
...transactionData
415423
},
416-
{ common, freeze: false }
424+
{ common }
417425
)
418-
transaction.v = new BN(toBuffer(networkId))
419-
transaction.r = transaction.s = new BN(toBuffer(0))
420426

421-
const ledgerResult = await eth.signTransaction(
422-
path,
423-
transaction.serialize().toString('hex')
424-
)
425-
let v = ledgerResult.v.toString(16)
426-
// EIP155 support. check/recalc signature v value.
427-
const rv = parseInt(v, 16)
428-
let cv = networkId * 2 + 35
429-
if (rv !== cv && (rv & cv) !== rv) {
430-
cv += 1 // add signature v bit.
427+
let unsignedTx = transaction.getMessageToSign(false)
428+
429+
// If this is not an EIP1559 transaction then it is legacy and it needs to be
430+
// rlp encoded before being passed to ledger
431+
if (!transaction.supports(Capability.EIP1559FeeMarket)) {
432+
unsignedTx = rlp.encode(unsignedTx)
431433
}
432-
v = cv.toString(16)
433-
transaction.v = new BN(toBuffer(`0x${v}`))
434-
transaction.r = new BN(toBuffer(`0x${ledgerResult.r}`))
435-
transaction.s = new BN(toBuffer(`0x${ledgerResult.s}`))
436434

437-
return `0x${transaction.serialize().toString('hex')}`
435+
const { v, r, s } = await eth.signTransaction(path, unsignedTx)
436+
437+
// Reconstruct the signed transaction
438+
const signedTx = Transaction.fromTxData(
439+
{
440+
...transactionData,
441+
v: `0x${v}`,
442+
r: `0x${r}`,
443+
s: `0x${s}`
444+
},
445+
{ common }
446+
)
447+
448+
return `0x${signedTx.serialize().toString('hex')}`
438449
} catch (error) {
439450
throw error
440451
}

0 commit comments

Comments
 (0)