From 12fad78716134afc178246400d66320089e8ddd5 Mon Sep 17 00:00:00 2001 From: Tomas Martykan Date: Wed, 11 Dec 2024 14:41:43 +0100 Subject: [PATCH] feat(connect): improve serializeEthereumTx --- .../ethereum/api/ethereumSignTransaction.ts | 13 +--- .../src/api/ethereum/ethereumSignTx.ts | 62 ++++++++++++++----- 2 files changed, 47 insertions(+), 28 deletions(-) diff --git a/packages/connect/src/api/ethereum/api/ethereumSignTransaction.ts b/packages/connect/src/api/ethereum/api/ethereumSignTransaction.ts index 8c43809344a..571e3b79eba 100644 --- a/packages/connect/src/api/ethereum/api/ethereumSignTransaction.ts +++ b/packages/connect/src/api/ethereum/api/ethereumSignTransaction.ts @@ -1,7 +1,5 @@ // origin: https://github.com/trezor/connect/blob/develop/src/js/core/methods/EthereumSignTransaction.js -import { FeeMarketEIP1559TxData, LegacyTxData } from '@ethereumjs/tx'; - import { MessagesSchema } from '@trezor/protobuf'; import { Assert } from '@trezor/schema-utils'; @@ -155,16 +153,7 @@ export default class EthereumSignTransaction extends AbstractMethod< definitions, ); - const txData = { - ...tx, - ...signature, - type: isLegacy ? 0 : 2, // 0 for legacy, 2 for EIP-1559 - gasPrice: isLegacy ? tx.gasPrice : undefined, - maxFeePerGas: !isLegacy ? tx.maxFeePerGas : undefined, - maxPriorityFeePerGas: !isLegacy ? tx.maxPriorityFeePerGas : undefined, - } as LegacyTxData | FeeMarketEIP1559TxData; - - const serializedTx = helper.serializeEthereumTx(txData, tx.chainId); + const serializedTx = helper.serializeEthereumTx(tx, signature, isLegacy); return { ...signature, serializedTx }; } diff --git a/packages/connect/src/api/ethereum/ethereumSignTx.ts b/packages/connect/src/api/ethereum/ethereumSignTx.ts index a844bc1d308..b92f48b694c 100644 --- a/packages/connect/src/api/ethereum/ethereumSignTx.ts +++ b/packages/connect/src/api/ethereum/ethereumSignTx.ts @@ -7,7 +7,11 @@ import { MessagesSchema } from '@trezor/protobuf'; import { PROTO, ERRORS } from '../../constants'; import type { TypedCall } from '../../device/DeviceCommands'; -import type { EthereumAccessList } from '../../types/api/ethereum'; +import type { + EthereumAccessList, + EthereumTransaction, + EthereumTransactionEIP1559, +} from '../../types/api/ethereum'; import { addHexPrefix, deepTransform } from '../../utils/formatUtils'; const splitString = (str?: string, len?: number) => { @@ -26,9 +30,9 @@ const processTxRequest = async ( data?: string, chain_id?: number, ): Promise<{ - v: string; - r: string; - s: string; + v: `0x${string}`; + r: `0x${string}`; + s: `0x${string}`; }> => { if (!request.data_length) { let v = request.signature_v; @@ -59,24 +63,50 @@ const processTxRequest = async ( const deepHexPrefix = deepTransform(addHexPrefix); -export const serializeEthereumTx = ( - txData: LegacyTxData | FeeMarketEIP1559TxData, - chainId: number, -) => { +export const getCommonForChain = (chainId: number) => { + // @ethereumjs/tx directly supported chains + if (Common.isSupportedChainId(BigInt(chainId))) return new Common({ chain: chainId }); + // @ethereumjs/tx doesn't support ETC (chain 61) by default // and it needs to be declared as custom chain // see: https://github.com/ethereumjs/ethereumjs-tx/blob/master/examples/custom-chain-tx.ts - const txOptions = - chainId === 61 + if (chainId === 61) + return Common.custom( + { name: 'ethereum-classic', networkId: 1, chainId: 61 }, + { baseChain: Chain.Mainnet, hardfork: Hardfork.Petersburg }, + ); + + // other chains + return Common.custom({ chainId }); +}; + +export const serializeEthereumTx = ( + tx: EthereumTransactionEIP1559 | EthereumTransaction, + signature: { v: `0x${string}`; r: `0x${string}`; s: `0x${string}` }, + isLegacy: boolean, +) => { + const txData = deepHexPrefix({ + ...tx, + ...signature, + type: isLegacy ? 0 : 2, // 0 for legacy, 2 for EIP-1559 + ...(isLegacy ? { - common: Common.custom( - { name: 'ethereum-classic', networkId: 1, chainId: 61 }, - { baseChain: Chain.Mainnet, hardfork: Hardfork.Petersburg }, - ), + gasPrice: tx.gasPrice, + maxFeePerGas: undefined, + maxPriorityFeePerGas: undefined, } - : { chain: chainId }; + : { + gasPrice: undefined, + maxFeePerGas: tx.maxFeePerGas, + maxPriorityFeePerGas: tx.maxPriorityFeePerGas, + }), + }) satisfies LegacyTxData | FeeMarketEIP1559TxData; + + const txOptions = { + common: getCommonForChain(tx.chainId), + }; - const ethTx = TransactionFactory.fromTxData(deepHexPrefix(txData), txOptions); + const ethTx = TransactionFactory.fromTxData(txData, txOptions); return `0x${Buffer.from(ethTx.serialize()).toString('hex')}`; };