permissionless
Version:
A utility library for working with ERC-4337
203 lines (175 loc) • 6.42 kB
text/typescript
import { getAddress, zeroAddress } from "viem"
import { describe, expect } from "vitest"
import { testWithRpc } from "../../../permissionless-test/src/testWithRpc"
import {
getCoreSmartAccounts,
getPublicClient
} from "../../../permissionless-test/src/utils"
import { signTypedData } from "./signTypedData"
const typedData = {
domain: {
name: "Ether Mail",
version: "1",
chainId: 1,
verifyingContract: getAddress(
"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" as const,
message: {
from: {
name: "Cow",
wallet: "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
},
to: {
name: "Bob",
wallet: "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
},
contents: "Hello, Bob!"
}
}
describe.each(getCoreSmartAccounts())(
"signTypedData $name",
({
getSmartAccountClient,
isEip1271Compliant,
supportsEntryPointV06,
supportsEntryPointV07,
supportsEntryPointV08,
name
}) => {
testWithRpc.skipIf(isEip1271Compliant || !supportsEntryPointV06)(
"not isEip1271Compliant_v06",
async ({ rpc }) => {
const smartClient = await getSmartAccountClient({
entryPoint: {
version: "0.6"
},
...rpc
})
await expect(async () =>
signTypedData(smartClient, typedData)
).rejects.toThrow()
}
)
testWithRpc.skipIf(!isEip1271Compliant || !supportsEntryPointV06)(
"isEip1271Compliant_v06",
async ({ rpc }) => {
const { anvilRpc } = rpc
const smartClient = await getSmartAccountClient({
entryPoint: {
version: "0.6"
},
...rpc
})
const signature = await signTypedData(smartClient, typedData)
const publicClient = getPublicClient(anvilRpc)
const isVerified = await publicClient.verifyTypedData({
...typedData,
address: smartClient.account.address,
signature
})
expect(isVerified).toBeTruthy()
}
)
testWithRpc.skipIf(isEip1271Compliant || !supportsEntryPointV07)(
"not isEip1271Compliant_v07",
async ({ rpc }) => {
const smartClient = await getSmartAccountClient({
entryPoint: {
version: "0.7"
},
...rpc
})
await expect(async () =>
signTypedData(smartClient, typedData)
).rejects.toThrow()
}
)
testWithRpc.skipIf(!isEip1271Compliant || !supportsEntryPointV07)(
"isEip1271Compliant_v07",
async ({ rpc }) => {
const { anvilRpc } = rpc
const smartClient = await getSmartAccountClient({
entryPoint: {
version: "0.7"
},
...rpc
})
const signature = await signTypedData(smartClient, typedData)
const publicClient = getPublicClient(anvilRpc)
if (name === "LightAccount 2.0.0") {
// LightAccount 2.0.0 doesn't support EIP-1271
return
}
if (name.includes("Safe 7579")) {
// Due to 7579 launchpad, we can't verify the signature before deploying the account.
await smartClient.sendTransaction({
calls: [{ to: zeroAddress, value: 0n }]
})
}
const isVerified = await publicClient.verifyTypedData({
...typedData,
address: smartClient.account.address,
signature
})
expect(isVerified).toBeTruthy()
}
)
testWithRpc.skipIf(isEip1271Compliant || !supportsEntryPointV08)(
"not isEip1271Compliant_v08",
async ({ rpc }) => {
const smartClient = await getSmartAccountClient({
entryPoint: {
version: "0.8"
},
...rpc
})
await expect(async () =>
signTypedData(smartClient, typedData)
).rejects.toThrow()
}
)
testWithRpc.skipIf(!isEip1271Compliant || !supportsEntryPointV08)(
"isEip1271Compliant_v08",
async ({ rpc }) => {
const { anvilRpc } = rpc
const smartClient = await getSmartAccountClient({
entryPoint: {
version: "0.8"
},
...rpc
})
const signature = await signTypedData(smartClient, typedData)
const publicClient = getPublicClient(anvilRpc)
if (name === "LightAccount 2.0.0") {
// LightAccount 2.0.0 doesn't support EIP-1271
return
}
if (name.includes("Safe 7579")) {
// Due to 7579 launchpad, we can't verify the signature before deploying the account.
await smartClient.sendTransaction({
calls: [{ to: zeroAddress, value: 0n }]
})
}
const isVerified = await publicClient.verifyTypedData({
...typedData,
address: smartClient.account.address,
signature
})
expect(isVerified).toBeTruthy()
}
)
}
)