From 121a856c0670bc1add8e46e51f6c399b7bbf61e0 Mon Sep 17 00:00:00 2001 From: danijelTxFusion Date: Thu, 14 Nov 2024 02:35:26 +0100 Subject: [PATCH 1/2] fix: add `parseEip712Transaction` util function --- .changeset/eleven-socks-reflect.md | 5 ++ src/zksync/index.ts | 1 + .../utils/parseEip712Transaction.test.ts | 68 +++++++++++++++++++ src/zksync/utils/parseEip712Transaction.ts | 57 ++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 .changeset/eleven-socks-reflect.md create mode 100644 src/zksync/utils/parseEip712Transaction.test.ts create mode 100644 src/zksync/utils/parseEip712Transaction.ts diff --git a/.changeset/eleven-socks-reflect.md b/.changeset/eleven-socks-reflect.md new file mode 100644 index 0000000000..09a848ac62 --- /dev/null +++ b/.changeset/eleven-socks-reflect.md @@ -0,0 +1,5 @@ +--- +"viem": patch +--- + +Added `parseEip712Transaction` util function in ZKsync extension. diff --git a/src/zksync/index.ts b/src/zksync/index.ts index 5e576828f3..99754b75f3 100644 --- a/src/zksync/index.ts +++ b/src/zksync/index.ts @@ -281,3 +281,4 @@ export { type GetGeneralPaymasterInputReturnType, getGeneralPaymasterInput, } from './utils/paymaster/getGeneralPaymasterInput.js' +export { parseEip712Transaction } from './utils/parseEip712Transaction.js' diff --git a/src/zksync/utils/parseEip712Transaction.test.ts b/src/zksync/utils/parseEip712Transaction.test.ts new file mode 100644 index 0000000000..f6b1d1fda5 --- /dev/null +++ b/src/zksync/utils/parseEip712Transaction.test.ts @@ -0,0 +1,68 @@ +import { expect, test } from 'vitest' +import { parseEip712Transaction } from './parseEip712Transaction.js' + +test('default', () => { + const serializedTransaction = + '0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0' + const transaction = parseEip712Transaction(serializedTransaction) + expect(transaction).toEqual({ + type: 'eip712', + nonce: 0, + maxPriorityFeePerGas: 0n, + maxFeePerGas: 0n, + gas: 0n, + to: '0xa61464658afeaf65cccaafd3a512b69a83b77618', + value: 1000000n, + data: '0x', + chainId: 270, + from: '0x36615cf349d7f6344891b1e7ca7c72883f5dc049', + v: 1n, + r: '0x73a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24a', + s: '0x2f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a', + gasPerPubdata: 50000n, + factoryDeps: [], + customSignature: '0x', + paymaster: undefined, + paymasterInput: undefined, + }) +}) + +test('with paymaster', async () => { + const serializedTransaction = + '0x71f8c880808080808000820144808082014494000000000000000000000000000000000000000082c350c0b841bb509f381d29a038bd2f700bd6a1f1138edfd7a3cf7234c13a03b01a023a30aa53e6bd5e6a50fdcdcf74587c9395b8a314690abbc85aadab5ebcb7678994eacf1bf85b94fd9ae5ebb0f6656f4b77a0e99dcbc5138d54b0bab8448c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000' + + const transaction = parseEip712Transaction(serializedTransaction) + expect(transaction).toEqual({ + type: 'eip712', + nonce: 0, + maxPriorityFeePerGas: 0n, + maxFeePerGas: 0n, + gas: 0n, + to: '0x', + value: 0n, + data: '0x00', + chainId: 324, + from: '0x0000000000000000000000000000000000000000', + v: 324n, + r: '0x', + s: '0x', + gasPerPubdata: 50000n, + factoryDeps: [], + customSignature: + '0xbb509f381d29a038bd2f700bd6a1f1138edfd7a3cf7234c13a03b01a023a30aa53e6bd5e6a50fdcdcf74587c9395b8a314690abbc85aadab5ebcb7678994eacf1b', + paymaster: '0xfd9ae5ebb0f6656f4b77a0e99dcbc5138d54b0ba', + paymasterInput: + '0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000', + }) +}) + +test('not eip712 transaction', () => { + const serializedTransaction = + '0x73a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aaf87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a' + + try { + parseEip712Transaction(serializedTransaction) + } catch (e: any) { + expect(e.shortMessage).toEqual('transaction type must be eip712') + } +}) diff --git a/src/zksync/utils/parseEip712Transaction.ts b/src/zksync/utils/parseEip712Transaction.ts new file mode 100644 index 0000000000..9e178a04c1 --- /dev/null +++ b/src/zksync/utils/parseEip712Transaction.ts @@ -0,0 +1,57 @@ +import { BaseError } from '../../errors/base.js' +import type { Hex } from '../../types/misc.js' +import { + fromHex, + fromRlp, + hexToBigInt, + hexToNumber, +} from '../../utils/index.js' +import type { ZksyncTransactionSerializableEIP712 } from '../types/transaction.js' + +export function parseEip712Transaction( + transaction: Hex, +): ZksyncTransactionSerializableEIP712 { + const payload = fromHex(transaction, 'bytes') + if (payload[0] !== 113) throw new BaseError('transaction type must be eip712') + + function validHex(value: Hex): Hex { + if (!value || value === '0x') return '0x0' + return value + } + + function parsePaymasterArray(arr: Hex[]) { + if (arr.length === 0) return undefined + if (arr.length !== 2) + throw new BaseError( + `Invalid paymaster parameters, expected to have length of 2, found ${arr.length}!`, + ) + + return { + paymaster: arr[0], + paymasterInput: arr[1], + } + } + + const raw = fromRlp(payload.slice(1)) as Hex[] + const paymasterParams = parsePaymasterArray(raw[15] as unknown as Hex[]) + return { + type: 'eip712', + nonce: hexToNumber(validHex(raw[0])), + maxPriorityFeePerGas: hexToBigInt(validHex(raw[1])), + maxFeePerGas: hexToBigInt(validHex(raw[2])), + gas: hexToBigInt(validHex(raw[3])), + to: raw[4], + value: hexToBigInt(validHex(raw[5])), + data: raw[6], + v: hexToBigInt(validHex(raw[7])), + r: raw[8], + s: raw[9], + chainId: hexToNumber(validHex(raw[10])), + from: raw[11], + gasPerPubdata: hexToBigInt(validHex(raw[12])), + factoryDeps: raw[13] as unknown as Hex[], + customSignature: raw[14], + paymaster: paymasterParams?.paymaster, + paymasterInput: paymasterParams?.paymasterInput, + } +} From 5fd181cd4973fbab9b65438d0e760fa8bb8979b3 Mon Sep 17 00:00:00 2001 From: danijelTxFusion Date: Thu, 14 Nov 2024 02:38:54 +0100 Subject: [PATCH 2/2] fix(sites,zksync): add `parseEip712Transaction` util function --- .../utilities/parseEip712Transaction.md | 43 +++++++++++++++++++ site/sidebar.ts | 4 ++ 2 files changed, 47 insertions(+) create mode 100644 site/pages/zksync/utilities/parseEip712Transaction.md diff --git a/site/pages/zksync/utilities/parseEip712Transaction.md b/site/pages/zksync/utilities/parseEip712Transaction.md new file mode 100644 index 0000000000..5c55ca799f --- /dev/null +++ b/site/pages/zksync/utilities/parseEip712Transaction.md @@ -0,0 +1,43 @@ +--- +description: Parse EIP712 transaction. +--- + +# parseEip712Transaction + +Parses a serialized EIP712 transaction. + +## Import + +```ts +import { parseEip712Transaction } from 'viem/zksync' +``` + +## Usage + +```ts +import { parseEip712Transaction } from 'viem/zksync' + +const serializedTransaction = + '0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0' +const transaction = parseEip712Transaction(serializedTransaction) +``` + +## Returns + +`ZksyncTransactionSerializableEIP712` + +The ZKsync EIP712 transaction. + +## Parameters + +### tx + +- **Type:** [`Hex`](/docs/glossary/types#hex) + +The serialized EIP712 transaction. + +```ts +const serializedTransaction = + '0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0' +const transaction = parseEip712Transaction(serializedTransaction) +``` \ No newline at end of file diff --git a/site/sidebar.ts b/site/sidebar.ts index 837cd9baef..0683caac44 100644 --- a/site/sidebar.ts +++ b/site/sidebar.ts @@ -1757,6 +1757,10 @@ export const sidebar = { }, ], }, + { + text: 'parseEip712Transaction', + link: '/zksync/utilities/parseEip712Transaction', + }, ], }, ],