Skip to content

Commit

Permalink
added test file and a method with a TODO
Browse files Browse the repository at this point in the history
  • Loading branch information
Muhammad-Altabba committed Jun 25, 2024
1 parent b7cce7f commit c63f05e
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 12 deletions.
48 changes: 38 additions & 10 deletions src/Eip712.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,23 +62,29 @@ function arrayToPaymasterParams(arr: Uint8Array): PaymasterParams | undefined {

export class EIP712 {
static getSignInput(transaction: Eip712TxData): Eip712SignedInput {
const maxFeePerGas = toHex(transaction.maxFeePerGas || transaction.gasPrice || 0n);
const maxPriorityFeePerGas = toHex(transaction.maxPriorityFeePerGas || maxFeePerGas);
const gasPerPubdataByteLimit = toHex(
transaction.customData?.gasPerPubdata || DEFAULT_GAS_PER_PUBDATA_LIMIT,
);
const maxFeePerGas = toBigInt(transaction.maxFeePerGas || transaction.gasPrice || 0n);
const maxPriorityFeePerGas = toBigInt(transaction.maxPriorityFeePerGas || maxFeePerGas);
const gasPerPubdataByteLimit =
transaction.customData?.gasPerPubdata || DEFAULT_GAS_PER_PUBDATA_LIMIT;
return {
txType: transaction.type || EIP712_TX_TYPE,
from: transaction.from ? toHex(transaction.from) : undefined,
to: transaction.to ? toHex(transaction.to) : undefined,
gasLimit: transaction.gasLimit ? toBigInt(transaction.gasLimit) : 0,
from: transaction.from
? typeof transaction.from === 'string'
? transaction.from
: toHex(transaction.from)
: undefined,
to: transaction.to
? typeof transaction.to === 'string'
? transaction.to
: toHex(transaction.to)
: undefined,
gasLimit: transaction.gasLimit ? toBigInt(transaction.gasLimit) : 0n,
gasPerPubdataByteLimit: gasPerPubdataByteLimit,
customData: transaction.customData,
maxFeePerGas,
maxPriorityFeePerGas,
paymaster: transaction.customData?.paymasterParams?.paymaster || ZERO_ADDRESS,
nonce: transaction.nonce ? toBigInt(transaction.nonce) : 0,
value: transaction.value ? toHex(transaction.value) : '0x0',
value: transaction.value ? toBigInt(transaction.value) : 0n,
data: transaction.data ? toHex(transaction.data) : '0x',
factoryDeps:
transaction.customData?.factoryDeps?.map((dep: Bytes) => hashBytecode(dep)) || [],
Expand Down Expand Up @@ -322,6 +328,28 @@ export class EIP712Signer {
return new EIP712Transaction(tx).sign(toBytes(this.web3Account.privateKey)).getSignature();
}

/**
* Hashes the transaction request using EIP712.
*
* @param transaction The transaction request that needs to be hashed.
* @returns A hash (digest) of the transaction request.
*
* @throws {Error} If `transaction.chainId` is not set.
*/
static getSignedDigest(transaction: Eip712TxData): Bytes {
if (!transaction.chainId) {
throw Error("Transaction chainId isn't set!");
}
const domain = {
name: 'zkSync',
version: '2',
chainId: transaction.chainId,
};
// TODO: Implement replacement of the following line
// @ts-ignore
return ethers.TypedDataEncoder.hash(domain, EIP712_TYPES, EIP712.getSignInput(transaction));
}

/**
* Returns zkSync Era EIP712 domain.
*/
Expand Down
9 changes: 7 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -867,17 +867,22 @@ export interface TypedDataField {
type: string;
}

export type Eip712TxData = FeeMarketEIP1559TxData & {
export type Eip712TxData = Omit<FeeMarketEIP1559TxData, 'gasPrice'> & {
/** The custom data for EIP712 transaction metadata. */
customData?: null | Eip712Meta;
from?: Address;
hash?: string;
signature?: string;
/**
* The transaction's gas price. To be used if maxPriorityFeePerGas and maxFeePerGas were not provided
*/
gasPrice?: Numbers | Uint8Array | null;
};

export type Eip712SignedInput = FeeMarketEIP1559TxData & {
customData?: null | Eip712Meta;
data: Bytes;
value: Bytes;
value: Numbers;
nonce: Numbers;
gasLimit: Numbers;
maxFeePerGas: Numbers;
Expand Down
75 changes: 75 additions & 0 deletions test/unit/signer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// import '../custom-matchers';
import { EIP712Signer } from '../../src/Eip712';
import { ADDRESS1, ADDRESS2 } from '../utils';
import { ZeroAddress } from '../../src/types';
import { DEFAULT_GAS_PER_PUBDATA_LIMIT, EIP712_TX_TYPE } from '../../src/constants';
import { EIP712 } from '../../src/Eip712';

describe('EIP712Signer', () => {
describe('#getSignInput()', () => {
it('should return a populated transaction', async () => {
const tx = {
txType: EIP712_TX_TYPE,
from: ADDRESS1,
to: ADDRESS2,
gasLimit: 21_000n,
gasPerPubdataByteLimit: DEFAULT_GAS_PER_PUBDATA_LIMIT,
maxFeePerGas: 250_000_000n,
maxPriorityFeePerGas: 250_000_000n,
paymaster: ZeroAddress,
nonce: 0,
value: 7_000_000n,
data: '0x',
factoryDeps: [],
paymasterInput: '0x',
};

const result = EIP712.getSignInput({
type: EIP712_TX_TYPE,
to: ADDRESS2,
value: 7_000_000n,
from: ADDRESS1,
nonce: 0,
chainId: 270n,
gasPrice: 250_000_000n,
gasLimit: 21_000n,
customData: {},
});
expect(result).toEqual(tx);
});
it('should return a populated transaction with default values', async () => {
const tx = {
txType: EIP712_TX_TYPE,
from: ADDRESS1,
to: ADDRESS2,
gasLimit: 0n,
gasPerPubdataByteLimit: DEFAULT_GAS_PER_PUBDATA_LIMIT,
maxFeePerGas: 0n,
maxPriorityFeePerGas: 0n,
paymaster: ZeroAddress,
nonce: 0,
value: 0n,
data: '0x',
factoryDeps: [],
paymasterInput: '0x',
};

const result = EIP712.getSignInput({
type: EIP712_TX_TYPE,
to: ADDRESS2,
from: ADDRESS1,
});
expect(result).toEqual(tx);
});
});

describe('#getSignedDigest()', () => {
it('should throw an error when chain ID is not specified', async () => {
try {
EIP712Signer.getSignedDigest({});
} catch (e) {
expect((e as Error).message).toEqual("Transaction chainId isn't set!");
}
});
});
});

0 comments on commit c63f05e

Please sign in to comment.