Skip to content

Commit

Permalink
fix: sign typed data, and add test for sign typed data
Browse files Browse the repository at this point in the history
  • Loading branch information
howydev committed Dec 27, 2024
1 parent 018e0b2 commit b89a8d5
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 2 deletions.
95 changes: 94 additions & 1 deletion account-kit/smart-contracts/src/ma-v2/client/client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
zeroAddress,
getContract,
hashMessage,
hashTypedData,
} from "viem";
import { createSMAV2AccountClient } from "./client.js";
import { local070Instance } from "~test/instances.js";
Expand Down Expand Up @@ -130,7 +131,7 @@ describe("MA v2 Tests", async () => {
accountContract.read.isValidSignature([hashMessage(message), signature])
).resolves.toEqual(isValidSigSuccess);

// connect session key and send tx with session key
// connect session key
let sessionKeyClient = await createSMAV2AccountClient({
chain: instance.chain,
signer: sessionKey,
Expand All @@ -146,6 +147,98 @@ describe("MA v2 Tests", async () => {
).resolves.toEqual(isValidSigSuccess);
});

it("successfully sign + validate typed data messages, for native and single signer validation", async () => {
const provider = (await givenConnectedProvider({ signer })).extend(
installValidationActions
);

await setBalance(instance.getClient(), {
address: provider.getAddress(),
value: parseEther("2"),
});

const accountContract = getContract({
address: provider.getAddress(),
abi: semiModularAccountBytecodeAbi,
client,
});

// UO deploys the account to test 1271 against
const result = await provider.installValidation({
validationConfig: {
moduleAddress: getDefaultSingleSignerValidationModuleAddress(
provider.chain
),
entityId: 1,
isGlobal: true,
isSignatureValidation: true,
isUserOpValidation: true,
},
selectors: [],
installData: SingleSignerValidationModule.encodeOnInstallData({
entityId: 1,
signer: await sessionKey.getAddress(),
}),
hooks: [],
});

await provider.waitForUserOperationTransaction(result);

const typedData = {
domain: {
name: "Ether Mail",
version: "1",
chainId: 1,
verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
},
types: {
Person: [
{ name: "name", type: "string" },
{ name: "wallet", type: "address" },
],
Mail: [
{ name: "from", type: "Person" },
{ name: "to", type: "Person" },
{ name: "contents", type: "string" },
],
},
primaryType: "Mail",
message: {
from: {
name: "Cow",
wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
},
to: {
name: "Bob",
wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
},
contents: "Hello, Bob!",
},
};

const hashedMessageTypedData = hashTypedData(typedData);
let signature = await provider.signTypedData({ typedData });

await expect(
accountContract.read.isValidSignature([hashedMessageTypedData, signature])
).resolves.toEqual(isValidSigSuccess);

// connect session key
let sessionKeyClient = await createSMAV2AccountClient({
chain: instance.chain,
signer: sessionKey,
transport: custom(instance.getClient()),
accountAddress: provider.getAddress(),
signerEntity: { entityId: 1, isGlobalValidation: true },
});

signature = await sessionKeyClient.signTypedData({ typedData });

await expect(
accountContract.read.isValidSignature([hashedMessageTypedData, signature])
).resolves.toEqual(isValidSigSuccess);
});

it("adds a session key with no permissions", async () => {
let provider = (await givenConnectedProvider({ signer })).extend(
installValidationActions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export const singleSignerMessageSigner = (
chainId: Number(chain.id),
verifyingContract:
getDefaultSingleSignerValidationModuleAddress(chain),
salt: accountAddress,
salt: concatHex([`0x${"00".repeat(12)}`, accountAddress]),
},
types: {
ReplaySafeHash: [{ name: "hash", type: "bytes32" }],
Expand Down

0 comments on commit b89a8d5

Please sign in to comment.