Skip to content

Commit

Permalink
Showing 14 changed files with 326 additions and 282 deletions.
21 changes: 11 additions & 10 deletions src/contract.ts
Original file line number Diff line number Diff line change
@@ -17,10 +17,10 @@ import {
getDeployedContracts,
hashBytecode,
} from "./utils";
import {AccountAbstractionVersion, DeploymentType} from "./types";
import { AccountAbstractionVersion, DeploymentType } from "./types";

/* c8 ignore next */
export {Contract} from "ethers";
export { Contract } from "ethers";

export class ContractFactory<
A extends Array<any> = Array<any>,
@@ -69,7 +69,8 @@ export class ContractFactory<
}
}

if (overrides.customData &&
if (
overrides.customData &&
overrides.customData.factoryDeps != null &&
!Array.isArray(overrides.customData.factoryDeps)
) {
@@ -82,7 +83,7 @@ export class ContractFactory<
): Promise<ContractDeployTransaction> {
let constructorArgs: any[];
let overrides: ethers.Overrides = {
customData: {factoryDeps: [], salt: ethers.ZeroHash},
customData: { factoryDeps: [], salt: ethers.ZeroHash },
};

// The overrides will be popped out in this call:
@@ -169,9 +170,9 @@ export class ContractFactory<
...args: ContractMethodArgs<A>
): Promise<
BaseContract & { deploymentTransaction(): ContractTransactionResponse } & Omit<
I,
keyof BaseContract
>
I,
keyof BaseContract
>
> {
const contract = await super.deploy(...args);
const deployTxReceipt = await this.runner?.provider?.getTransactionReceipt(
@@ -189,9 +190,9 @@ export class ContractFactory<
contract.interface.fragments,
contract.runner,
) as BaseContract & { deploymentTransaction(): ContractTransactionResponse } & Omit<
I,
keyof BaseContract
>;
I,
keyof BaseContract
>;

// @ts-ignore
contractWithCorrectAddress.deploymentTransaction = () => contract.deploymentTransaction();
22 changes: 16 additions & 6 deletions src/signer.ts
Original file line number Diff line number Diff line change
@@ -74,7 +74,11 @@ export class EIP712Signer {
version: "2",
chainId: transaction.chainId,
};
return ethers.TypedDataEncoder.hash(domain, EIP712_TYPES, EIP712Signer.getSignInput(transaction));
return ethers.TypedDataEncoder.hash(
domain,
EIP712_TYPES,
EIP712Signer.getSignInput(transaction),
);
}

async getDomain(): Promise<ethers.TypedDataDomain> {
@@ -115,10 +119,13 @@ export class Signer extends AdapterL2(ethers.JsonRpcSigner) {
transaction.type = 0;
}
if (transaction.customData == null && transaction.type != EIP712_TX_TYPE) {
return await super.sendTransaction(transaction) as TransactionResponse;
return (await super.sendTransaction(transaction)) as TransactionResponse;
} else {
const address = await this.getAddress();
const from = transaction.from == null ? address : await ethers.resolveAddress(transaction.from as Address);
const from =
transaction.from == null
? address
: await ethers.resolveAddress(transaction.from as Address);
if (from.toLowerCase() != address.toLowerCase()) {
throw new Error("Transaction `from` address mismatch");
}
@@ -203,10 +210,13 @@ export class VoidSigner extends AdapterL2(ethers.VoidSigner) {
transaction.type = 0;
}
if (transaction.customData == null && transaction.type != EIP712_TX_TYPE) {
return await super.sendTransaction(transaction) as TransactionResponse;
return (await super.sendTransaction(transaction)) as TransactionResponse;
} else {
const address = await this.getAddress();
const from = transaction.from == null ? address : await ethers.resolveAddress(transaction.from as Address);
const from =
transaction.from == null
? address
: await ethers.resolveAddress(transaction.from as Address);
if (from.toLowerCase() != address.toLowerCase()) {
throw new Error("Transaction `from` address mismatch");
}
@@ -265,4 +275,4 @@ export class L1VoidSigner extends AdapterL1(ethers.VoidSigner) {
return this;
}
}
/* c8 ignore stop */
/* c8 ignore stop */
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -299,7 +299,7 @@ export class Transaction extends ethers.Transaction {
if (tx.value != null) result.value = tx.value;
if (tx.chainId != null) result.chainId = tx.chainId;
if (tx.signature != null) result.signature = EthersSignature.from(tx.signature);
result.accessList = null
result.accessList = null;

if (tx.from != null) {
assertArgument(result.isSigned(), "unsigned transaction cannot define from", "tx", tx);
10 changes: 5 additions & 5 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {AbiCoder, BigNumberish, BytesLike, ethers, SignatureLike} from "ethers";
import { AbiCoder, BigNumberish, BytesLike, ethers, SignatureLike } from "ethers";
import {
Address,
DeploymentInfo,
@@ -9,12 +9,12 @@ import {
PriorityQueueType,
TransactionLike,
} from "./types";
import {Provider} from "./provider";
import {EIP712Signer} from "./signer";
import {IERC20__factory, IL1Bridge__factory} from "../typechain";
import { Provider } from "./provider";
import { EIP712Signer } from "./signer";
import { IERC20__factory, IL1Bridge__factory } from "../typechain";

export * from "./paymaster-utils";
export {EIP712_TYPES} from "./signer";
export { EIP712_TYPES } from "./signer";

export const ZKSYNC_MAIN_ABI = new ethers.Interface(require("../abi/IZkSync.json"));
export const CONTRACT_DEPLOYER = new ethers.Interface(require("../abi/IContractDeployer.json"));
41 changes: 21 additions & 20 deletions tests/integration/contract.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as chai from "chai";
import "../custom-matchers";
import {ContractFactory, Provider, types, Wallet, Contract} from "../../src";
import {ethers} from "ethers";
import { ContractFactory, Provider, types, Wallet, Contract } from "../../src";
import { ethers } from "ethers";

const {expect} = chai;
const { expect } = chai;

describe("ContractFactory", () => {
const PRIVATE_KEY = "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110";
@@ -107,9 +107,7 @@ describe("ContractFactory", () => {
wallet,
"createAccount",
);
const paymasterContract = await accountFactory.deploy(
await provider.l2TokenAddress(DAI_L1),
);
const paymasterContract = await accountFactory.deploy(await provider.l2TokenAddress(DAI_L1));

const code = await provider.getCode(await paymasterContract.getAddress());
expect(code).not.to.be.null;
@@ -120,7 +118,7 @@ describe("ContractFactory", () => {
const bytecode: string = require(storagePath).contracts["Storage.sol:Storage"].bin;
const factory = new ContractFactory(abi, bytecode, wallet, "create2");
const contract = await factory.deploy({
customData: {salt: ethers.hexlify(ethers.randomBytes(32))},
customData: { salt: ethers.hexlify(ethers.randomBytes(32)) },
});

const code = await provider.getCode(await contract.getAddress());
@@ -132,7 +130,7 @@ describe("ContractFactory", () => {
const bytecode: string = require(tokenPath).bytecode;
const factory = new ContractFactory(abi, bytecode, wallet, "create2");
const contract = await factory.deploy("Ducat", "Ducat", 18, {
customData: {salt: ethers.hexlify(ethers.randomBytes(32))},
customData: { salt: ethers.hexlify(ethers.randomBytes(32)) },
});

const code = await provider.getCode(await contract.getAddress());
@@ -149,7 +147,7 @@ describe("ContractFactory", () => {
const contract = (await factory.deploy({
customData: {
salt: ethers.hexlify(ethers.randomBytes(32)),
factoryDeps: [require(demoPath).contracts["Foo.sol:Foo"].bin]
factoryDeps: [require(demoPath).contracts["Foo.sol:Foo"].bin],
},
})) as Contract;

@@ -168,7 +166,7 @@ describe("ContractFactory", () => {
);
const paymasterContract = await accountFactory.deploy(
await provider.l2TokenAddress(DAI_L1),
{customData: {salt: ethers.hexlify(ethers.randomBytes(32))}},
{ customData: { salt: ethers.hexlify(ethers.randomBytes(32)) } },
);

const code = await provider.getCode(await paymasterContract.getAddress());
@@ -205,7 +203,7 @@ describe("ContractFactory", () => {

try {
await factory.getDeployTransaction("Ducat", "Ducat", 18, {
customData: {salt: "0000"}
customData: { salt: "0000" },
});
} catch (e) {
expect(e.message).to.be.equal("Invalid salt provided.");
@@ -219,7 +217,7 @@ describe("ContractFactory", () => {

try {
await factory.getDeployTransaction("Ducat", "Ducat", 18, {
customData: {salt: "0x000"}
customData: { salt: "0x000" },
});
} catch (e) {
expect(e.message).to.be.equal("Invalid salt provided.");
@@ -235,24 +233,27 @@ describe("ContractFactory", () => {
await factory.getDeployTransaction("Ducat", "Ducat", 18, {
customData: {
salt: ethers.hexlify(ethers.randomBytes(32)),
factoryDeps: "0"
}
factoryDeps: "0",
},
});
} catch (e) {
expect(e.message).to.be.equal("Invalid 'factoryDeps' format. It should be an array of bytecodes.");
expect(e.message).to.be.equal(
"Invalid 'factoryDeps' format. It should be an array of bytecodes.",
);
}

try {
await factory.getDeployTransaction("Ducat", "Ducat", 18, {
customData: {
salt: ethers.hexlify(ethers.randomBytes(32)),
factoryDeps: ""
}
factoryDeps: "",
},
});
} catch (e) {
expect(e.message).to.be.equal("Invalid 'factoryDeps' format. It should be an array of bytecodes.");
expect(e.message).to.be.equal(
"Invalid 'factoryDeps' format. It should be an array of bytecodes.",
);
}
}).timeout(10_000);

})
});
});
24 changes: 10 additions & 14 deletions tests/integration/format.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as chai from "chai";
import "../custom-matchers";
import {Provider, types} from "../../src";
import {ethers} from "ethers";
import { Provider, types } from "../../src";
import { ethers } from "ethers";

const {expect} = chai;
const { expect } = chai;

describe("format", () => {
const provider = Provider.getDefaultProvider(types.Network.Localhost);
@@ -17,8 +17,8 @@ describe("format", () => {
gasLimit: BigInt(21_000),
value: BigInt(1_000_000),
nonce: BigInt(0),
data: "0x"
}
data: "0x",
};
const result = provider._wrapTransactionResponse(value, await provider.getNetwork());
expect(result.to).to.be.equal(ethers.ZeroAddress);
});
@@ -32,8 +32,8 @@ describe("format", () => {
value: BigInt(1_000_000),
nonce: BigInt(0),
data: "0x",
creates: null
}
creates: null,
};
const result = provider._wrapTransactionResponse(value, await provider.getNetwork());
expect(result.to).to.be.null;
});
@@ -48,8 +48,8 @@ describe("format", () => {
value: BigInt(1_000_000),
nonce: BigInt(0),
data: "0x",
accessList: null
}
accessList: null,
};
const result = provider._wrapTransactionResponse(value, await provider.getNetwork());
expect(result.accessList).to.has.lengthOf(0);
});
@@ -64,7 +64,7 @@ describe("format", () => {
value: BigInt(1_000_000),
nonce: BigInt(0),
data: "0x",
}
};
const result = provider._wrapTransactionResponse(value, await provider.getNetwork());
expect(result.blockHash).to.be.null;
});
@@ -77,8 +77,4 @@ describe("format", () => {
}
});
});

});



22 changes: 12 additions & 10 deletions tests/integration/provider.test.ts

Large diffs are not rendered by default.

61 changes: 30 additions & 31 deletions tests/integration/types.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {expect} from "chai";
import { expect } from "chai";
import "../custom-matchers";
import {Provider, types, utils, Wallet} from "../../src";
import { Provider, types, utils, Wallet } from "../../src";

describe("types", () => {
const PRIVATE_KEY = "0x7726827caac94a7f9e1b160f7ea819f172f7b6f9d2a97f992c38edeab82d4110";
@@ -60,7 +60,7 @@ describe("types", () => {

describe("#getTransaction()", () => {
it("should return the transaction receipt", async () => {
const result = await receipt.getTransaction()
const result = await receipt.getTransaction();
expect(result.hash).to.be.equal(receipt.hash);
});
});
@@ -97,7 +97,7 @@ describe("types", () => {

describe("#getTransaction()", () => {
it("should return the transaction in block based on provided index", async () => {
const result = await block.getTransaction(0)
const result = await block.getTransaction(0);
expect(result).not.to.be.null;
});
});
@@ -107,7 +107,8 @@ describe("types", () => {
try {
await block.getPrefetchedTransaction(0);
} catch (e) {
expect(e.message.startsWith("transactions were not prefetched with block request")).to.be.true
expect(e.message.startsWith("transactions were not prefetched with block request"))
.to.be.true;
}
});
});
@@ -132,18 +133,21 @@ describe("types", () => {
});
await tx.wait();
const receipt = await provider.getTransactionReceipt(tx.hash);
log = new types.Log({
blockHash: receipt.blockHash,
blockNumber: receipt.blockNumber,
transactionHash: receipt.hash,
transactionIndex: receipt.index,
data: null,
address: utils.L2_ETH_TOKEN_ADDRESS,
index: 0,
removed: false,
topics: [],
l1BatchNumber: 0,
}, provider);
log = new types.Log(
{
blockHash: receipt.blockHash,
blockNumber: receipt.blockNumber,
transactionHash: receipt.hash,
transactionIndex: receipt.index,
data: null,
address: utils.L2_ETH_TOKEN_ADDRESS,
index: 0,
removed: false,
topics: [],
l1BatchNumber: 0,
},
provider,
);
});

describe("#getTransaction()", () => {
@@ -185,41 +189,44 @@ describe("types", () => {
type: utils.EIP712_TX_TYPE,
to: RECEIVER,
value: 1_000_000,
nonce: 1
nonce: 1,
});
eip712Tx = types.Transaction.from(signedEip712Tx);

const signedLegacyTx = await wallet.signTransaction({
to: RECEIVER,
value: 1_000_000,
nonce: 1
nonce: 1,
});
eip1559Tx = types.Transaction.from(signedLegacyTx);
});

describe("#serialized()", () => {
it("should return the serialized EIP1559 transaction", async () => {
const tx = "0x02f863800180808094a61464658afeaf65cccaafd3a512b69a83b77618830f424080c080a0e15275d6af28bbafc770d1a919f9a01ace6720239888c403219793c31744b2d2a07dd1b1070cedb5795afb295bedd9b4404fecd31f66a0e8f09747aa261bfb317f"
const tx =
"0x02f863800180808094a61464658afeaf65cccaafd3a512b69a83b77618830f424080c080a0e15275d6af28bbafc770d1a919f9a01ace6720239888c403219793c31744b2d2a07dd1b1070cedb5795afb295bedd9b4404fecd31f66a0e8f09747aa261bfb317f";
const result = eip1559Tx.serialized;
expect(result).to.be.equal(tx);
});

it("should return the serialized EIP712 transaction", async () => {
const tx = "0x71f88e01840ee6b280840ee6b28083025b0b94a61464658afeaf65cccaafd3a512b69a83b77618830f42408082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c0b841de26c3845dd9032d8fb6e761c89e155181e3cbd12d4294fec4065dafaa8628af482ba6f5361aa016b5371b00ff5e8222a148ced3d485f3cba9d25c08761b25b51cc0"
const tx =
"0x71f88e01840ee6b280840ee6b28083025b0b94a61464658afeaf65cccaafd3a512b69a83b77618830f42408082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c0b841de26c3845dd9032d8fb6e761c89e155181e3cbd12d4294fec4065dafaa8628af482ba6f5361aa016b5371b00ff5e8222a148ced3d485f3cba9d25c08761b25b51cc0";
const result = eip712Tx.serialized;
expect(result).to.be.equal(tx);
});
});

describe("#unsignedSerialized()", () => {
it("should return the unsigned serialized EIP1559 transaction", async () => {
const tx = "0x02e0800180808094a61464658afeaf65cccaafd3a512b69a83b77618830f424080c0"
const tx = "0x02e0800180808094a61464658afeaf65cccaafd3a512b69a83b77618830f424080c0";
const result = eip1559Tx.unsignedSerialized;
expect(result).to.be.equal(tx);
});

it("should return the unsigned serialized EIP712 transaction", async () => {
const tx = "0x71f88e01840ee6b280840ee6b28083025b0b94a61464658afeaf65cccaafd3a512b69a83b77618830f42408082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c0b841de26c3845dd9032d8fb6e761c89e155181e3cbd12d4294fec4065dafaa8628af482ba6f5361aa016b5371b00ff5e8222a148ced3d485f3cba9d25c08761b25b51cc0"
const tx =
"0x71f88e01840ee6b280840ee6b28083025b0b94a61464658afeaf65cccaafd3a512b69a83b77618830f42408082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c0b841de26c3845dd9032d8fb6e761c89e155181e3cbd12d4294fec4065dafaa8628af482ba6f5361aa016b5371b00ff5e8222a148ced3d485f3cba9d25c08761b25b51cc0";
const result = eip712Tx.unsignedSerialized;
expect(result).to.be.equal(tx);
});
@@ -250,11 +257,3 @@ describe("types", () => {
});
});
});








36 changes: 22 additions & 14 deletions tests/integration/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as chai from "chai";
import "../custom-matchers";
import {Provider, types, utils, EIP712Signer } from "../../src";
import {ethers} from "ethers";
import { Provider, types, utils, EIP712Signer } from "../../src";
import { ethers } from "ethers";

const {expect} = chai;
const { expect } = chai;

describe("utils", () => {
const ADDRESS = "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049";
@@ -14,17 +14,23 @@ describe("utils", () => {
describe("#isMessageSignatureCorrect()", () => {
it("should return true for a valid message signature", async () => {
const message = "Hello, world!";
const signature = await (new ethers.Wallet(PRIVATE_KEY)).signMessage(message);
const signature = await new ethers.Wallet(PRIVATE_KEY).signMessage(message);

const result = await utils.isMessageSignatureCorrect(provider, ADDRESS, message, signature);
expect(result).to.be.true;
});

it("should return false for an invalid message signature", async () => {
const message = "Hello!";
const invalidSignature = "0xb04f825363596418c630425916f73447d636094a75e47b45e2eb59d8a6c7d5035355f03b903b84700376f0efa23f3b095815776c5c6daf2b371a0a61b5f703451b";
const invalidSignature =
"0xb04f825363596418c630425916f73447d636094a75e47b45e2eb59d8a6c7d5035355f03b903b84700376f0efa23f3b095815776c5c6daf2b371a0a61b5f703451b";

const result = await utils.isMessageSignatureCorrect(provider, ADDRESS, message, invalidSignature);
const result = await utils.isMessageSignatureCorrect(
provider,
ADDRESS,
message,
invalidSignature,
);
expect(result).to.be.false;
});
});
@@ -36,12 +42,12 @@ describe("utils", () => {
chainId: 270,
from: ADDRESS,
to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618",
value: BigInt(7_000_000)
value: BigInt(7_000_000),
};

const eip712Signer = new EIP712Signer(
new ethers.Wallet(PRIVATE_KEY),
Number((await provider.getNetwork()).chainId)
Number((await provider.getNetwork()).chainId),
);

const signature = await eip712Signer.sign(tx);
@@ -52,25 +58,27 @@ describe("utils", () => {
await eip712Signer.getDomain(),
utils.EIP712_TYPES,
EIP712Signer.getSignInput(tx),
signature);
signature,
);

expect(result).to.be.true;
});

it("should return false for an invalid typed data signature", async () => {
const invalidSignature = "0x5ea12f3d54a1624d7e7f5161dbf6ab746c3335e643b2966264e740cf8e10e9b64b0251fb79d9a5b11730387085a0d58f105926f72e20242ecb274639991939ca1b";
const invalidSignature =
"0x5ea12f3d54a1624d7e7f5161dbf6ab746c3335e643b2966264e740cf8e10e9b64b0251fb79d9a5b11730387085a0d58f105926f72e20242ecb274639991939ca1b";

const tx: types.TransactionRequest = {
type: 113,
chainId: 270,
from: ADDRESS,
to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618",
value: BigInt(1_000_000)
value: BigInt(1_000_000),
};

const eip712Signer = new EIP712Signer(
new ethers.Wallet(PRIVATE_KEY),
Number((await provider.getNetwork()).chainId)
Number((await provider.getNetwork()).chainId),
);

const result = await utils.isTypedDataSignatureCorrect(
@@ -79,9 +87,9 @@ describe("utils", () => {
await eip712Signer.getDomain(),
utils.EIP712_TYPES,
EIP712Signer.getSignInput(tx),
invalidSignature);
invalidSignature,
);
expect(result).to.be.false;
});
});

});
58 changes: 32 additions & 26 deletions tests/integration/wallet.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as chai from "chai";
import "../custom-matchers";
import {Provider, types, utils, Wallet} from "../../src";
import {ethers} from "ethers";
import { Provider, types, utils, Wallet } from "../../src";
import { ethers } from "ethers";
import * as fs from "fs";

const {expect} = chai;
const { expect } = chai;

describe("Wallet", () => {
const ADDRESS = "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049";
@@ -87,14 +87,16 @@ describe("Wallet", () => {
try {
await wallet.approveERC20(utils.ETH_ADDRESS, 5);
} catch (e) {
expect(e.message).to.be.equal("ETH token can't be approved. The address of the token does not exist on L1.")
expect(e.message).to.be.equal(
"ETH token can't be approved. The address of the token does not exist on L1.",
);
}
}).timeout(5_000);
});

describe("#getBaseCost()", () => {
it("should return a base cost of L1 transaction", async () => {
const result = await wallet.getBaseCost({gasLimit: 100_000});
const result = await wallet.getBaseCost({ gasLimit: 100_000 });
expect(result).not.to.be.null;
});
});
@@ -140,7 +142,7 @@ describe("Wallet", () => {
try {
wallet.ethWallet();
} catch (e) {
expect(e.message).to.be.equal("L1 provider missing: use `connectToL1` to specify")
expect(e.message).to.be.equal("L1 provider missing: use `connectToL1` to specify");
}
});
});
@@ -410,9 +412,8 @@ describe("Wallet", () => {
try {
await wallet.claimFailedDeposit(tx.hash);
} catch (e) {
expect(e.message).to.be.equal("Cannot claim successful deposit")
expect(e.message).to.be.equal("Cannot claim successful deposit");
}

}).timeout(30_000);
});

@@ -462,16 +463,19 @@ describe("Wallet", () => {
expect(result).to.be.deep.equal(FEE_DATA);
}).timeout(10_000);


it("should throw an error when there is not enough balance for the deposit", async () => {
try {
const randomWallet = new Wallet(ethers.Wallet.createRandom().privateKey, provider, ethProvider);
const randomWallet = new Wallet(
ethers.Wallet.createRandom().privateKey,
provider,
ethProvider,
);
await randomWallet.getFullRequiredDepositFee({
token: DAI_L1,
to: await wallet.getAddress(),
});
} catch (e) {
expect(e.message).to.include("Not enough balance for deposit.")
expect(e.message).to.include("Not enough balance for deposit.");
}
}).timeout(10_000);
});
@@ -596,18 +600,20 @@ describe("Wallet", () => {
const result = await wallet.signTransaction({
type: 2,
to: RECEIVER,
value: BigInt(7_000_000_000)
value: BigInt(7_000_000_000),
});
expect(result).to.be.equal("0x02f869808080840ee6b2808094a61464658afeaf65cccaafd3a512b69a83b776188501a13b860080c001a0ea6c3f7588b7b4e5652e0372aa09d772b59689ee0e51445b3b7d69bffd5d9e77a046387a8dfa24ab22d3427cd85035b91abc28e1876813873ea0b41f2bdc9ef778");
expect(result).to.be.equal(
"0x02f869808080840ee6b2808094a61464658afeaf65cccaafd3a512b69a83b776188501a13b860080c001a0ea6c3f7588b7b4e5652e0372aa09d772b59689ee0e51445b3b7d69bffd5d9e77a046387a8dfa24ab22d3427cd85035b91abc28e1876813873ea0b41f2bdc9ef778",
);
}).timeout(25_000);

it("should return a signed EIP712 transaction", async () => {
const result = await wallet.signTransaction({
type: utils.EIP712_TX_TYPE,
to: RECEIVER,
value: ethers.parseEther("1")
value: ethers.parseEther("1"),
});
expect(result).not.to.be.null
expect(result).not.to.be.null;
}).timeout(25_000);

it("should throw an error when `tx.from` is mismatched from private key", async () => {
@@ -616,33 +622,33 @@ describe("Wallet", () => {
type: utils.EIP712_TX_TYPE,
from: RECEIVER,
to: RECEIVER,
value: 7_000_000_000
})
value: 7_000_000_000,
});
} catch (e) {
expect(e.message).to.be.equal("Transaction `from` address mismatch")
expect(e.message).to.be.equal("Transaction `from` address mismatch");
}
}).timeout(25_000);
});

describe("#populateTransaction()", () => {
it("should return a populated transaction", async () => {
const TX = {
to: '0xa61464658AfeAf65CccaaFD3a512b69A83B77618',
to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618",
value: BigInt(7_000_000_000),
type: utils.EIP712_TX_TYPE,
from: '0x36615Cf349d7F6344891B1e7CA7C72883F5dc049',
from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049",
gasLimit: BigInt(154_379),
chainId: BigInt(270),
data: '0x',
customData: {gasPerPubdata: 50_000, factoryDeps: []},
gasPrice: BigInt(250_000_000)
}
data: "0x",
customData: { gasPerPubdata: 50_000, factoryDeps: [] },
gasPrice: BigInt(250_000_000),
};

const result = await wallet.populateTransaction({
type: utils.EIP712_TX_TYPE,
to: RECEIVER,
value: 7_000_000_000
})
value: 7_000_000_000,
});
expect(result).to.be.deepEqualExcluding(TX, ["nonce"]);
}).timeout(25_000);
});
194 changes: 97 additions & 97 deletions tests/tokens.json
Original file line number Diff line number Diff line change
@@ -1,98 +1,98 @@
[
{
"name": "DAI",
"symbol": "DAI",
"decimals": 18,
"address": "0x70a0F165d6f8054d0d0CF8dFd4DD2005f0AF6B55"
},
{
"name": "wBTC",
"symbol": "wBTC",
"decimals": 8,
"address": "0x1C552d7B40b38Fb1235697Bed7b8e1e47B46e5BA"
},
{
"name": "BAT",
"symbol": "BAT",
"decimals": 18,
"address": "0xdF2Ff03eAAfae59fA7fd30D4f91ab045B3d5D95D"
},
{
"name": "GNT",
"symbol": "GNT",
"decimals": 18,
"address": "0xeF81A0BB8819F94EEf15992F31555a282d7009d1"
},
{
"name": "MLTT",
"symbol": "MLTT",
"decimals": 18,
"address": "0x9ad574a765F65Ec554780c2b5D97979Ed1957d30"
},
{
"name": "DAIK",
"symbol": "DAIK",
"decimals": 18,
"address": "0x266B465D9D37cF6001d38b8e3f839fAE0e10D619"
},
{
"name": "wBTCK",
"symbol": "wBTCK",
"decimals": 8,
"address": "0x05789138d7838a4707FFB45EA5B2c498B1e8Be3c"
},
{
"name": "BATK",
"symbol": "BATS",
"decimals": 18,
"address": "0xfeC8FE20C644fab5d37B86E821A29F1abfEdFc55"
},
{
"name": "GNTK",
"symbol": "GNTS",
"decimals": 18,
"address": "0xde617bf595d8090c63350CA3916b13FBD79f0E0a"
},
{
"name": "MLTTK",
"symbol": "MLTTS",
"decimals": 18,
"address": "0x0B827231D3ECE7906361723170701941f5813191"
},
{
"name": "DAIL",
"symbol": "DAIL",
"decimals": 18,
"address": "0x4EDe5c04d0eF5aDDD222cc7D3C4cbE23Ac7fD4F4"
},
{
"name": "wBTCL",
"symbol": "wBTCP",
"decimals": 8,
"address": "0x2E694B999D7746Dcf3864E9C2F47a4daEBD65721"
},
{
"name": "BATL",
"symbol": "BATW",
"decimals": 18,
"address": "0x0a1D1D084645a46E9E019da345684308701855b6"
},
{
"name": "GNTL",
"symbol": "GNTW",
"decimals": 18,
"address": "0x1630bcE01eb41A9Fd5d49a14e5c6D52b1B127d17"
},
{
"name": "MLTTL",
"symbol": "MLTTW",
"decimals": 18,
"address": "0xa60bc9ae6a6967CAC6D8b08e12a2EF087348Cd32"
},
{
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"address": "0x4A470422bFf67C34a3A565106118023059fa4E34"
}
]
{
"name": "DAI",
"symbol": "DAI",
"decimals": 18,
"address": "0x70a0F165d6f8054d0d0CF8dFd4DD2005f0AF6B55"
},
{
"name": "wBTC",
"symbol": "wBTC",
"decimals": 8,
"address": "0x1C552d7B40b38Fb1235697Bed7b8e1e47B46e5BA"
},
{
"name": "BAT",
"symbol": "BAT",
"decimals": 18,
"address": "0xdF2Ff03eAAfae59fA7fd30D4f91ab045B3d5D95D"
},
{
"name": "GNT",
"symbol": "GNT",
"decimals": 18,
"address": "0xeF81A0BB8819F94EEf15992F31555a282d7009d1"
},
{
"name": "MLTT",
"symbol": "MLTT",
"decimals": 18,
"address": "0x9ad574a765F65Ec554780c2b5D97979Ed1957d30"
},
{
"name": "DAIK",
"symbol": "DAIK",
"decimals": 18,
"address": "0x266B465D9D37cF6001d38b8e3f839fAE0e10D619"
},
{
"name": "wBTCK",
"symbol": "wBTCK",
"decimals": 8,
"address": "0x05789138d7838a4707FFB45EA5B2c498B1e8Be3c"
},
{
"name": "BATK",
"symbol": "BATS",
"decimals": 18,
"address": "0xfeC8FE20C644fab5d37B86E821A29F1abfEdFc55"
},
{
"name": "GNTK",
"symbol": "GNTS",
"decimals": 18,
"address": "0xde617bf595d8090c63350CA3916b13FBD79f0E0a"
},
{
"name": "MLTTK",
"symbol": "MLTTS",
"decimals": 18,
"address": "0x0B827231D3ECE7906361723170701941f5813191"
},
{
"name": "DAIL",
"symbol": "DAIL",
"decimals": 18,
"address": "0x4EDe5c04d0eF5aDDD222cc7D3C4cbE23Ac7fD4F4"
},
{
"name": "wBTCL",
"symbol": "wBTCP",
"decimals": 8,
"address": "0x2E694B999D7746Dcf3864E9C2F47a4daEBD65721"
},
{
"name": "BATL",
"symbol": "BATW",
"decimals": 18,
"address": "0x0a1D1D084645a46E9E019da345684308701855b6"
},
{
"name": "GNTL",
"symbol": "GNTW",
"decimals": 18,
"address": "0x1630bcE01eb41A9Fd5d49a14e5c6D52b1B127d17"
},
{
"name": "MLTTL",
"symbol": "MLTTW",
"decimals": 18,
"address": "0xa60bc9ae6a6967CAC6D8b08e12a2EF087348Cd32"
},
{
"name": "Wrapped Ether",
"symbol": "WETH",
"decimals": 18,
"address": "0x4A470422bFf67C34a3A565106118023059fa4E34"
}
]
22 changes: 11 additions & 11 deletions tests/unit/paymaster.test.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import * as chai from "chai";
import "../custom-matchers";
import {utils, types} from "../../src";
import { utils, types } from "../../src";

const { expect } = chai;

describe("getPaymasterParams()", () => {
it("should return encoded parameters for the general paymaster", async () => {
const params: types.PaymasterParams = {
paymaster: '0x0a67078A35745947A37A552174aFe724D8180c25',
paymasterInput: '0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000'
}
paymaster: "0x0a67078A35745947A37A552174aFe724D8180c25",
paymasterInput:
"0x8c5a344500000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
};

const result = utils.getPaymasterParams(
"0x0a67078A35745947A37A552174aFe724D8180c25", {
const result = utils.getPaymasterParams("0x0a67078A35745947A37A552174aFe724D8180c25", {
type: "General",
innerInput: new Uint8Array(),
});
@@ -21,12 +21,12 @@ describe("getPaymasterParams()", () => {

it("should return encoded parameters for the general paymaster", async () => {
const params: types.PaymasterParams = {
paymaster: '0x0a67078A35745947A37A552174aFe724D8180c25',
paymasterInput: '0x949431dc00000000000000000000000065c899b5fb8eb9ae4da51d67e1fc417c7cb7e964000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000'
}
paymaster: "0x0a67078A35745947A37A552174aFe724D8180c25",
paymasterInput:
"0x949431dc00000000000000000000000065c899b5fb8eb9ae4da51d67e1fc417c7cb7e964000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
};

const result = utils.getPaymasterParams(
"0x0a67078A35745947A37A552174aFe724D8180c25", {
const result = utils.getPaymasterParams("0x0a67078A35745947A37A552174aFe724D8180c25", {
type: "ApprovalBased",
token: "0x65C899B5fb8Eb9ae4da51D67E1fc417c7CB7e964",
minimalAllowance: BigInt(1),
6 changes: 3 additions & 3 deletions tests/unit/signer.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as chai from "chai";
import "../custom-matchers";
import {utils, EIP712Signer} from "../../src";
import {ethers} from "ethers";
import { utils, EIP712Signer } from "../../src";
import { ethers } from "ethers";

const { expect } = chai;

@@ -33,7 +33,7 @@ describe("EIP712Signer", () => {
chainId: BigInt(270),
gasPrice: BigInt(250_000_000),
gasLimit: BigInt(21_000),
customData: {}
customData: {},
});
expect(result).to.be.deep.equal(tx);
});
89 changes: 55 additions & 34 deletions tests/unit/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import {expect} from "chai";
import {types, utils} from "../../src";
import {ethers} from "ethers";
import { expect } from "chai";
import { types, utils } from "../../src";
import { ethers } from "ethers";

describe("utils", () => {
describe("#getHashedL2ToL1Msg()", () => {
it("should return a hashed L2 to L1 message", async () => {
const withdrawETHMessage = "0x6c0960f936615cf349d7f6344891b1e7ca7c72883f5dc04900000000000000000000000000000000000000000000000000000001a13b8600"
const withdrawETHMessageHash = "0xd8c80ecb64619e343f57c3b133c6c6d8dd0572dd3488f1ca3276c5b7fd3a938d"
const result = utils.getHashedL2ToL1Msg("0x36615Cf349d7F6344891B1e7CA7C72883F5dc049", withdrawETHMessage, 0)
expect(result).to.be.equal(withdrawETHMessageHash)
const withdrawETHMessage =
"0x6c0960f936615cf349d7f6344891b1e7ca7c72883f5dc04900000000000000000000000000000000000000000000000000000001a13b8600";
const withdrawETHMessageHash =
"0xd8c80ecb64619e343f57c3b133c6c6d8dd0572dd3488f1ca3276c5b7fd3a938d";
const result = utils.getHashedL2ToL1Msg(
"0x36615Cf349d7F6344891B1e7CA7C72883F5dc049",
withdrawETHMessage,
0,
);
expect(result).to.be.equal(withdrawETHMessageHash);
});
});

@@ -97,9 +103,11 @@ describe("utils", () => {

it("should throw an error when `tx.from` is not specified", async () => {
try {
utils.serializeEip712({chainId: 270});
utils.serializeEip712({ chainId: 270 });
} catch (e) {
expect(e.message).to.be.equal("Explicitly providing `from` field is required for EIP712 transactions");
expect(e.message).to.be.equal(
"Explicitly providing `from` field is required for EIP712 transactions",
);
}
});

@@ -109,32 +117,42 @@ describe("utils", () => {
chainId: 270,
from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049",
customData: {
customSignature: ""
}
customSignature: "",
},
});
} catch (e) {
expect(e.message).to.be.equal("Empty signatures are not supported");
}
});

it("should return a serialized transaction with populated default values", async () => {
const tx = "0x71ea8080808080808082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";
const result = utils.serializeEip712({
chainId: 270,
from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049"
}, null);
const tx =
"0x71ea8080808080808082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";
const result = utils.serializeEip712(
{
chainId: 270,
from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049",
},
null,
);
expect(result).to.be.equal(tx);
});

it("should return a serialized transaction with provided signature", async () => {
const tx = "0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";
const signature = ethers.Signature.from("0x73a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aaf87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a");
const result = utils.serializeEip712({
chainId: 270,
from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049",
to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618",
value: 1_000_000
}, signature);
const tx =
"0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";
const signature = ethers.Signature.from(
"0x73a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aaf87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a",
);
const result = utils.serializeEip712(
{
chainId: 270,
from: "0x36615Cf349d7F6344891B1e7CA7C72883F5dc049",
to: "0xa61464658AfeAf65CccaaFD3a512b69A83B77618",
value: 1_000_000,
},
signature,
);
expect(result).to.be.equal(tx);
});
});
@@ -176,11 +194,12 @@ describe("utils", () => {
try {
utils.hashBytecode(`0x${"00020000000000020009000000000002".repeat(2)}`);
} catch (e) {
expect(e.message).to.be.equal(`Bytecode can not be longer than ${utils.MAX_BYTECODE_LEN_BYTES} bytes`);
expect(e.message).to.be.equal(
`Bytecode can not be longer than ${utils.MAX_BYTECODE_LEN_BYTES} bytes`,
);
}
});


// it("should throw an error when bytecode is bigger and maximum allowed length", async () => {
// try {
// utils.hashBytecode("0x" + "00020000000000020009000000000002".repeat(utils.MAX_BYTECODE_LEN_BYTES+1));
@@ -207,12 +226,13 @@ describe("utils", () => {
gasPerPubdata: BigInt(50000),
factoryDeps: [],
customSignature: "0x",
paymasterParams: null
paymasterParams: null,
},
hash: "0x9ed410ce33179ac1ff6b721060605afc72d64febfe0c08cacab5a246602131ee"
}
hash: "0x9ed410ce33179ac1ff6b721060605afc72d64febfe0c08cacab5a246602131ee",
};

const serializedTx = "0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";
const serializedTx =
"0x71f87f8080808094a61464658afeaf65cccaafd3a512b69a83b77618830f42408001a073a20167b8d23b610b058c05368174495adf7da3a4ed4a57eb6dbdeb1fafc24aa02f87530d663a0d061f69bb564d2c6fb46ae5ae776bbd4bd2a2a4478b9cd1b42a82010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";
const result = utils.parseEip712(serializedTx);
expect(result).to.be.deep.equal(tx);
});
@@ -233,12 +253,13 @@ describe("utils", () => {
gasPerPubdata: BigInt(50000),
factoryDeps: [],
customSignature: "0x",
paymasterParams: null
paymasterParams: null,
},
hash: "0x7d3aab3e3d06d6a702228d911c2a9afaccddd52514fb89dc9d0ff81a67bfff04"
}
hash: "0x7d3aab3e3d06d6a702228d911c2a9afaccddd52514fb89dc9d0ff81a67bfff04",
};

const serializedTx = "0x71f83e8080808094a61464658afeaf65cccaafd3a512b69a83b77618808082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";
const serializedTx =
"0x71f83e8080808094a61464658afeaf65cccaafd3a512b69a83b77618808082010e808082010e9436615cf349d7f6344891b1e7ca7c72883f5dc04982c350c080c0";

const result = utils.parseEip712(serializedTx);
expect(result).to.be.deep.equal(tx);

0 comments on commit c8849e1

Please sign in to comment.