mirror of
https://github.com/getwax/wax.git
synced 2026-01-09 23:27:58 -05:00
136 lines
3.8 KiB
TypeScript
136 lines
3.8 KiB
TypeScript
import { ERC4337ZKPPasswordClient } from "@getwax/circuits";
|
|
import { expect } from "chai";
|
|
import { resolveProperties, ethers } from "ethers";
|
|
import sendUserOpAndWait from "./utils/sendUserOpAndWait";
|
|
import receiptOf from "./utils/receiptOf";
|
|
import {
|
|
MockGroth16Verifier__factory,
|
|
SafeZKPPasswordFactory__factory,
|
|
SafeZKPPasswordPlugin__factory,
|
|
} from "../../typechain-types";
|
|
import { setupTests } from "./utils/setupTests";
|
|
import { createUserOperation } from "./utils/createUserOp";
|
|
import { getUserOpHash } from "./utils/userOpUtils";
|
|
|
|
describe("SafeZKPPasswordPlugin", () => {
|
|
it("should pass the ERC4337 validation", async () => {
|
|
const {
|
|
bundlerProvider,
|
|
provider,
|
|
admin,
|
|
owner,
|
|
entryPointAddress,
|
|
deployer,
|
|
safeSingleton,
|
|
} = await setupTests();
|
|
|
|
const zkpClient = await ERC4337ZKPPasswordClient.create();
|
|
|
|
// Deploy zk password plugin
|
|
const safeZKPPasswordFactory = await deployer.connectOrDeploy(
|
|
SafeZKPPasswordFactory__factory,
|
|
[],
|
|
);
|
|
|
|
const signer = await provider.getSigner();
|
|
// TODO (merge-ok) Use real verifier from zkp dir
|
|
// https://github.com/getwax/wax/issues/143
|
|
const groth16Verifier = await new MockGroth16Verifier__factory(
|
|
signer,
|
|
).deploy();
|
|
|
|
const createArgs = [
|
|
safeSingleton,
|
|
entryPointAddress,
|
|
await owner.getAddress(),
|
|
0,
|
|
groth16Verifier,
|
|
] satisfies Parameters<typeof safeZKPPasswordFactory.create.staticCall>;
|
|
|
|
const accountAddress = await safeZKPPasswordFactory.create.staticCall(
|
|
...createArgs,
|
|
);
|
|
|
|
await receiptOf(safeZKPPasswordFactory.create(...createArgs));
|
|
|
|
// Native tokens for the pre-fund
|
|
await receiptOf(
|
|
admin.sendTransaction({
|
|
to: accountAddress,
|
|
value: ethers.parseEther("100"),
|
|
}),
|
|
);
|
|
|
|
// Construct userOp
|
|
const to = "0x42ef9B061d2B8416387FaA738Af7251668b0b142"; // Random address
|
|
const value = ethers.parseEther("1");
|
|
const data = "0x";
|
|
|
|
const userOpCallData =
|
|
SafeZKPPasswordPlugin__factory.createInterface().encodeFunctionData(
|
|
"execTransaction",
|
|
[to, value, data],
|
|
);
|
|
|
|
const encoder = ethers.AbiCoder.defaultAbiCoder();
|
|
const dummySignature = encoder.encode(
|
|
["uint256[2]", "uint256[2][2]", "uint256[2]"],
|
|
[
|
|
[0, 0],
|
|
[
|
|
[0, 0],
|
|
[0, 0],
|
|
],
|
|
[0, 0],
|
|
],
|
|
);
|
|
|
|
// Note: factoryParams is not used because we need to create both the safe
|
|
// proxy and the plugin, and 4337 currently only allows one contract
|
|
// creation in this step. Since we need an extra step anyway, it's simpler
|
|
// to do the whole create outside of 4337.
|
|
const factoryParams = {
|
|
factory: "0x",
|
|
factoryData: "0x",
|
|
};
|
|
|
|
const unsignedUserOperation = await createUserOperation(
|
|
provider,
|
|
bundlerProvider,
|
|
accountAddress,
|
|
factoryParams,
|
|
userOpCallData,
|
|
entryPointAddress,
|
|
dummySignature,
|
|
);
|
|
|
|
const resolvedUserOp = await resolveProperties(unsignedUserOperation);
|
|
const userOpHash = getUserOpHash(
|
|
resolvedUserOp,
|
|
entryPointAddress,
|
|
Number((await provider.getNetwork()).chainId),
|
|
);
|
|
|
|
const emojiPassword = "👻🎃🕸🦇🕷🪦";
|
|
const { signature } = await zkpClient.proveUserOp(
|
|
emojiPassword,
|
|
userOpHash,
|
|
);
|
|
|
|
const userOp = {
|
|
...unsignedUserOperation,
|
|
signature,
|
|
};
|
|
|
|
const recipientBalanceBefore = await provider.getBalance(to);
|
|
|
|
// Send userOp
|
|
await sendUserOpAndWait(userOp, entryPointAddress, bundlerProvider);
|
|
|
|
const recipientBalanceAfter = await provider.getBalance(to);
|
|
|
|
const expectedRecipientBalance = recipientBalanceBefore + value;
|
|
expect(recipientBalanceAfter).to.equal(expectedRecipientBalance);
|
|
});
|
|
});
|