diff --git a/.changeset/two-ties-sort.md b/.changeset/two-ties-sort.md new file mode 100644 index 0000000000..e5292d7b0c --- /dev/null +++ b/.changeset/two-ties-sort.md @@ -0,0 +1,5 @@ +--- +"viem": patch +--- + +Fixed an issue where `serializeTransaction` was incorrectly encoding zero-ish properties. diff --git a/src/utils/transaction/serializeTransaction.test.ts b/src/utils/transaction/serializeTransaction.test.ts index a1202e886c..0a1a49afac 100644 --- a/src/utils/transaction/serializeTransaction.test.ts +++ b/src/utils/transaction/serializeTransaction.test.ts @@ -41,6 +41,28 @@ describe('eip1559', () => { }) }) + test('default (all zeros)', () => { + const baseEip1559Zero = { + to: accounts[1].address, + nonce: 0, + chainId: 1, + maxFeePerGas: 0n, + maxPriorityFeePerGas: 0n, + value: 0n, + } satisfies TransactionSerializableEIP1559 + + const serialized = serializeTransaction(baseEip1559Zero) + + expect(serialized).toEqual( + '0x02dd01808080809470997970c51812dc3a010c7d01b50e0d17dc79c88080c0', + ) + expect(parseTransaction(serialized)).toEqual({ + chainId: 1, + to: accounts[1].address, + type: 'eip1559', + }) + }) + test('minimal (w/ maxFeePerGas)', () => { const args = { chainId: 1, @@ -223,6 +245,29 @@ describe('eip2930', () => { }) }) + test('default (all zeros)', () => { + const baseEip2930Zero = { + to: accounts[1].address, + nonce: 0, + chainId: 1, + value: 0n, + gasPrice: 0n, + accessList: [], + } satisfies TransactionSerializableEIP2930 + + const serialized = serializeTransaction(baseEip2930Zero) + + expect(serialized).toEqual( + '0x01dc018080809470997970c51812dc3a010c7d01b50e0d17dc79c88080c0', + ) + + expect(parseTransaction(serialized)).toEqual({ + chainId: 1, + to: accounts[1].address, + type: 'eip2930', + }) + }) + test('minimal (w/ accessList & gasPrice)', () => { const args = { chainId: 1, @@ -384,6 +429,26 @@ describe('legacy', () => { }) }) + test('default (all zeros)', () => { + const baseLegacyZero = { + to: accounts[1].address, + nonce: 0, + value: 0n, + gasPrice: 0n, + } satisfies TransactionSerializableLegacy + + const serialized = serializeTransaction(baseLegacyZero) + + expect(serialized).toEqual( + '0xda8080809470997970c51812dc3a010c7d01b50e0d17dc79c88080', + ) + + expect(parseTransaction(serialized)).toEqual({ + to: accounts[1].address, + type: 'legacy', + }) + }) + test('minimal (w/ gasPrice)', () => { const args = { gasPrice: parseGwei('2'), diff --git a/src/utils/transaction/serializeTransaction.ts b/src/utils/transaction/serializeTransaction.ts index cc59c4adef..ee9b8393d4 100644 --- a/src/utils/transaction/serializeTransaction.ts +++ b/src/utils/transaction/serializeTransaction.ts @@ -82,14 +82,12 @@ function serializeTransactionEIP1559( const serializedTransaction = [ toHex(chainId), - typeof nonce !== 'undefined' ? toHex(nonce) : '0x', - typeof maxPriorityFeePerGas !== 'undefined' - ? toHex(maxPriorityFeePerGas) - : '0x', - typeof maxFeePerGas !== 'undefined' ? toHex(maxFeePerGas) : '0x', - typeof gas !== 'undefined' ? toHex(gas) : '0x', + nonce ? toHex(nonce) : '0x', + maxPriorityFeePerGas ? toHex(maxPriorityFeePerGas) : '0x', + maxFeePerGas ? toHex(maxFeePerGas) : '0x', + gas ? toHex(gas) : '0x', to ?? '0x', - typeof value !== 'undefined' ? toHex(value) : '0x', + value ? toHex(value) : '0x', data ?? '0x', serializedAccessList, ] @@ -120,11 +118,11 @@ function serializeTransactionEIP2930( const serializedTransaction = [ toHex(chainId), - typeof nonce !== 'undefined' ? toHex(nonce) : '0x', - typeof gasPrice !== 'undefined' ? toHex(gasPrice) : '0x', - typeof gas !== 'undefined' ? toHex(gas) : '0x', + nonce ? toHex(nonce) : '0x', + gasPrice ? toHex(gasPrice) : '0x', + gas ? toHex(gas) : '0x', to ?? '0x', - typeof value !== 'undefined' ? toHex(value) : '0x', + value ? toHex(value) : '0x', data ?? '0x', serializedAccessList, ] @@ -151,11 +149,11 @@ function serializeTransactionLegacy( assertTransactionLegacy(transaction) let serializedTransaction = [ - typeof nonce !== 'undefined' ? toHex(nonce) : '0x', - typeof gasPrice !== 'undefined' ? toHex(gasPrice) : '0x', - typeof gas !== 'undefined' ? toHex(gas) : '0x', + nonce ? toHex(nonce) : '0x', + gasPrice ? toHex(gasPrice) : '0x', + gas ? toHex(gas) : '0x', to ?? '0x', - typeof value !== 'undefined' ? toHex(value) : '0x', + value ? toHex(value) : '0x', data ?? '0x', ]