Skip to content

Commit 56fdf93

Browse files
Add support for kernel + 7702 (#417)
1 parent 5494e69 commit 56fdf93

File tree

8 files changed

+135
-16
lines changed

8 files changed

+135
-16
lines changed

.changeset/full-peas-open.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"permissionless": patch
3+
---
4+
5+
Added authorisation support for installModule and installModules

packages/permissionless-test/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ export const getCoreSmartAccounts = (): Array<{
766766
supportsEntryPointV06: false,
767767
supportsEntryPointV07: true,
768768
supportsEntryPointV08: false,
769-
isEip7702Compliant: true,
769+
isEip7702Compliant: false,
770770
isEip1271Compliant: false
771771
},
772772
{

packages/permissionless/actions/erc7579/installModule.test.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
11
import { encodeAbiParameters, encodePacked, isHash, zeroAddress } from "viem"
2+
import { privateKeyToAccount } from "viem/accounts"
23
import { describe, expect } from "vitest"
34
import { testWithRpc } from "../../../permissionless-test/src/testWithRpc"
4-
import { getCoreSmartAccounts } from "../../../permissionless-test/src/utils"
5+
import {
6+
getCoreSmartAccounts,
7+
getPublicClient
8+
} from "../../../permissionless-test/src/utils"
59
import { erc7579Actions } from "../erc7579"
610
import { installModule } from "./installModule"
711

812
describe.each(getCoreSmartAccounts())(
913
"installModule $name",
10-
({ getErc7579SmartAccountClient, name }) => {
14+
({ getErc7579SmartAccountClient, name, isEip7702Compliant }) => {
1115
testWithRpc.skipIf(!getErc7579SmartAccountClient)(
1216
"installModule",
1317
async ({ rpc }) => {
1418
if (!getErc7579SmartAccountClient) {
1519
throw new Error("getErc7579SmartAccountClient not defined")
1620
}
1721

22+
const privateKey =
23+
"0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356"
24+
25+
const privateKeyAccount = privateKeyToAccount(privateKey)
26+
1827
const smartClientWithoutExtend =
1928
await getErc7579SmartAccountClient({
2029
entryPoint: {
2130
version: "0.7"
2231
},
32+
privateKey,
2333
...rpc
2434
})
2535

36+
const publicClient = getPublicClient(rpc.anvilRpc)
37+
2638
const smartClient = smartClientWithoutExtend.extend(
2739
erc7579Actions()
2840
)
@@ -47,7 +59,17 @@ describe.each(getCoreSmartAccounts())(
4759
)
4860
]
4961
)
50-
: moduleData
62+
: moduleData,
63+
authorization: isEip7702Compliant
64+
? await privateKeyAccount.signAuthorization({
65+
address: (smartClient.account as any)
66+
.implementation,
67+
chainId: smartClient.chain.id,
68+
nonce: await publicClient.getTransactionCount({
69+
address: smartClient.account.address
70+
})
71+
})
72+
: undefined
5173
})
5274

5375
expect(isHash(opHash)).toBe(true)
@@ -88,14 +110,22 @@ describe.each(getCoreSmartAccounts())(
88110
throw new Error("getErc7579SmartAccountClient not defined")
89111
}
90112

113+
const privateKey =
114+
"0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356"
115+
116+
const privateKeyAccount = privateKeyToAccount(privateKey)
117+
91118
const smartClientWithoutExtend =
92119
await getErc7579SmartAccountClient({
93120
entryPoint: {
94121
version: "0.7"
95122
},
123+
privateKey,
96124
...rpc
97125
})
98126

127+
const publicClient = getPublicClient(rpc.anvilRpc)
128+
99129
const smartClient = smartClientWithoutExtend.extend(
100130
erc7579Actions()
101131
)
@@ -112,7 +142,17 @@ describe.each(getCoreSmartAccounts())(
112142
value: 0n,
113143
data: "0x"
114144
}
115-
]
145+
],
146+
authorization: isEip7702Compliant
147+
? await privateKeyAccount.signAuthorization({
148+
address: (smartClient.account as any)
149+
.implementation,
150+
chainId: smartClient.chain.id,
151+
nonce: await publicClient.getTransactionCount({
152+
address: smartClient.account.address
153+
})
154+
})
155+
: undefined
116156
})
117157

118158
await smartClient.waitForUserOperationReceipt({

packages/permissionless/actions/erc7579/installModule.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Address, Client, Hex, OneOf } from "viem"
1+
import type { Address, Client, Hex, OneOf, SignedAuthorization } from "viem"
22
import {
33
type GetSmartAccountParameter,
44
type PaymasterActions,
@@ -13,6 +13,7 @@ import type { ModuleType } from "./supportsModule.js"
1313
export type InstallModuleParameters<
1414
TSmartAccount extends SmartAccount | undefined
1515
> = GetSmartAccountParameter<TSmartAccount> & {
16+
authorization?: SignedAuthorization<number> | undefined
1617
type: ModuleType
1718
address: Address
1819
maxFeePerGas?: bigint
@@ -63,6 +64,7 @@ export function installModule<TSmartAccount extends SmartAccount | undefined>(
6364
type,
6465
calls,
6566
paymaster,
67+
authorization,
6668
paymasterContext
6769
} = parameters
6870

@@ -91,6 +93,7 @@ export function installModule<TSmartAccount extends SmartAccount | undefined>(
9193
maxFeePerGas,
9294
maxPriorityFeePerGas,
9395
nonce,
96+
authorization,
9497
account
9598
})
9699
}

packages/permissionless/actions/erc7579/installModules.test.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
11
import { encodeAbiParameters, encodePacked, isHash, zeroAddress } from "viem"
2+
import { privateKeyToAccount } from "viem/accounts"
23
import { describe, expect } from "vitest"
34
import { testWithRpc } from "../../../permissionless-test/src/testWithRpc"
4-
import { getCoreSmartAccounts } from "../../../permissionless-test/src/utils"
5+
import {
6+
getCoreSmartAccounts,
7+
getPublicClient
8+
} from "../../../permissionless-test/src/utils"
59
import { erc7579Actions } from "../erc7579"
610
import { installModules } from "./installModules"
711

812
describe.each(getCoreSmartAccounts())(
913
"installModules $name",
10-
({ getErc7579SmartAccountClient, name }) => {
14+
({ getErc7579SmartAccountClient, name, isEip7702Compliant }) => {
1115
testWithRpc.skipIf(!getErc7579SmartAccountClient)(
1216
"installModules",
1317
async ({ rpc }) => {
1418
if (!getErc7579SmartAccountClient) {
1519
throw new Error("getErc7579SmartAccountClient not defined")
1620
}
1721

22+
const privateKey =
23+
"0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356"
24+
25+
const privateKeyAccount = privateKeyToAccount(privateKey)
26+
1827
const smartClientWithoutExtend =
1928
await getErc7579SmartAccountClient({
2029
entryPoint: {
2130
version: "0.7"
2231
},
32+
privateKey,
2333
...rpc
2434
})
2535

36+
const publicClient = getPublicClient(rpc.anvilRpc)
37+
2638
const smartClient = smartClientWithoutExtend.extend(
2739
erc7579Actions()
2840
)
@@ -41,6 +53,16 @@ describe.each(getCoreSmartAccounts())(
4153
data: "0x"
4254
}
4355
],
56+
authorization: isEip7702Compliant
57+
? await privateKeyAccount.signAuthorization({
58+
address: (smartClient.account as any)
59+
.implementation,
60+
chainId: smartClient.chain.id,
61+
nonce: await publicClient.getTransactionCount({
62+
address: smartClient.account.address
63+
})
64+
})
65+
: undefined,
4466
modules: [
4567
{
4668
type: "executor",
@@ -102,19 +124,36 @@ describe.each(getCoreSmartAccounts())(
102124
throw new Error("getErc7579SmartAccountClient not defined")
103125
}
104126

127+
const privateKey =
128+
"0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356"
129+
130+
const privateKeyAccount = privateKeyToAccount(privateKey)
131+
105132
const smartClientWithoutExtend =
106133
await getErc7579SmartAccountClient({
107134
entryPoint: {
108135
version: "0.7"
109136
},
137+
privateKey,
110138
...rpc
111139
})
140+
const publicClient = getPublicClient(rpc.anvilRpc)
112141

113142
const smartClient = smartClientWithoutExtend.extend(
114143
erc7579Actions()
115144
)
116145

117146
const userOpHash = await smartClient.sendUserOperation({
147+
authorization: isEip7702Compliant
148+
? await privateKeyAccount.signAuthorization({
149+
address: (smartClient.account as any)
150+
.implementation,
151+
chainId: smartClient.chain.id,
152+
nonce: await publicClient.getTransactionCount({
153+
address: smartClient.account.address
154+
})
155+
})
156+
: undefined,
118157
calls: [
119158
{
120159
to: smartClient.account.address,

packages/permissionless/actions/erc7579/installModules.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import type { Address, Chain, Client, Hex, Transport } from "viem"
1+
import type {
2+
Address,
3+
Chain,
4+
Client,
5+
Hex,
6+
SignedAuthorization,
7+
Transport
8+
} from "viem"
29
import {
310
type PaymasterActions,
411
type SmartAccount,
@@ -14,6 +21,7 @@ import {
1421
export type InstallModulesParameters<
1522
TSmartAccount extends SmartAccount | undefined
1623
> = EncodeInstallModuleParameters<TSmartAccount> & {
24+
authorization?: SignedAuthorization<number> | undefined
1725
maxFeePerGas?: bigint
1826
maxPriorityFeePerGas?: bigint
1927
nonce?: bigint
@@ -54,6 +62,7 @@ export async function installModules<
5462
modules,
5563
paymaster,
5664
paymasterContext,
65+
authorization,
5766
calls
5867
} = parameters
5968

@@ -80,6 +89,7 @@ export async function installModules<
8089
paymasterContext,
8190
maxFeePerGas,
8291
maxPriorityFeePerGas,
92+
authorization,
8393
nonce,
8494
account: account
8595
})

packages/permissionless/actions/erc7579/uninstallModule.test.ts

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
11
import { encodeAbiParameters, encodePacked, isHash, zeroAddress } from "viem"
2+
import { privateKeyToAccount } from "viem/accounts"
23
import { describe, expect } from "vitest"
34
import { testWithRpc } from "../../../permissionless-test/src/testWithRpc"
4-
import { getCoreSmartAccounts } from "../../../permissionless-test/src/utils"
5+
import {
6+
getCoreSmartAccounts,
7+
getPublicClient
8+
} from "../../../permissionless-test/src/utils"
59
import { erc7579Actions } from "../erc7579"
610
import { uninstallModule } from "./uninstallModule"
711

812
describe.each(getCoreSmartAccounts())(
913
"uninstallModule $name",
10-
({ getErc7579SmartAccountClient, name }) => {
14+
({ getErc7579SmartAccountClient, name, isEip7702Compliant }) => {
1115
testWithRpc.skipIf(!getErc7579SmartAccountClient)(
1216
"uninstallModule",
1317
async ({ rpc }) => {
1418
if (!getErc7579SmartAccountClient) {
1519
throw new Error("getErc7579SmartAccountClient not defined")
1620
}
1721

22+
const privateKey =
23+
"0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356"
24+
25+
const privateKeyAccount = privateKeyToAccount(privateKey)
26+
1827
const smartClientWithoutExtend =
1928
await getErc7579SmartAccountClient({
2029
entryPoint: {
2130
version: "0.7"
2231
},
32+
privateKey,
2333
...rpc
2434
})
2535

36+
const publicClient = getPublicClient(rpc.anvilRpc)
37+
2638
const smartClient = smartClientWithoutExtend.extend(
2739
erc7579Actions()
2840
)
@@ -46,7 +58,17 @@ describe.each(getCoreSmartAccounts())(
4658
)
4759
]
4860
)
49-
: moduleData
61+
: moduleData,
62+
authorization: isEip7702Compliant
63+
? await privateKeyAccount.signAuthorization({
64+
address: (smartClient.account as any)
65+
.implementation,
66+
chainId: smartClient.chain.id,
67+
nonce: await publicClient.getTransactionCount({
68+
address: smartClient.account.address
69+
})
70+
})
71+
: undefined
5072
})
5173

5274
await smartClient.waitForUserOperationReceipt({

packages/permissionless/actions/smartAccount/sendTransaction.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,16 @@ describe.each(getCoreSmartAccounts())(
7373
async ({ rpc }) => {
7474
const { anvilRpc } = rpc
7575

76-
const privateKeyAccount = privateKeyToAccount(
76+
const privateKey =
7777
"0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356"
78-
)
78+
79+
const privateKeyAccount = privateKeyToAccount(privateKey)
7980

8081
const smartClient = await getSmartAccountClient({
8182
entryPoint: {
8283
version: "0.7"
8384
},
84-
privateKey:
85-
"0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356", // anvil private key
85+
privateKey, // anvil private key
8686
...rpc
8787
})
8888

0 commit comments

Comments
 (0)