Skip to content

Improve 7579 functions #289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/metal-ravens-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"permissionless": patch
---

Added utility functions to encode 7579 function calldata
5 changes: 5 additions & 0 deletions .changeset/proud-rings-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"permissionless": patch
---

Added support to send calls with 7579 functions and override paymaster props
5 changes: 5 additions & 0 deletions .changeset/stale-roses-compare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"permissionless": patch
---

Added support for initData & deInitData
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe.each(getCoreSmartAccounts())(
account: smartClient.account,
type: "executor",
address: "0xc98B026383885F41d9a995f85FC480E9bb8bB891",
context: name.startsWith("Kernel 7579")
initData: name.startsWith("Kernel 7579")
? encodePacked(
["address", "bytes"],
[
Expand Down
91 changes: 45 additions & 46 deletions packages/permissionless/actions/erc7579/installModule.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,50 @@
import {
type Address,
type Client,
type Hex,
encodeFunctionData,
getAddress
} from "viem"
import type { Address, Client, Hex, Narrow, OneOf } from "viem"
import {
type GetSmartAccountParameter,
type PaymasterActions,
type SmartAccount,
type UserOperationCalls,
sendUserOperation
} from "viem/account-abstraction"
import { getAction, parseAccount } from "viem/utils"
import { AccountNotFoundError } from "../../errors"
import { type ModuleType, parseModuleTypeId } from "./supportsModule"
import { encodeInstallModule } from "../../utils"
import type { ModuleType } from "./supportsModule"

export type InstallModuleParameters<
TSmartAccount extends SmartAccount | undefined
TSmartAccount extends SmartAccount | undefined,
calls extends readonly unknown[] = readonly unknown[]
> = GetSmartAccountParameter<TSmartAccount> & {
type: ModuleType
address: Address
context: Hex
maxFeePerGas?: bigint
maxPriorityFeePerGas?: bigint
nonce?: bigint
}
calls?: UserOperationCalls<Narrow<calls>>
paymaster?:
| Address
| true
| {
/** Retrieves paymaster-related User Operation properties to be used for sending the User Operation. */
getPaymasterData?:
| PaymasterActions["getPaymasterData"]
| undefined
/** Retrieves paymaster-related User Operation properties to be used for gas estimation. */
getPaymasterStubData?:
| PaymasterActions["getPaymasterStubData"]
| undefined
}
| undefined
/** Paymaster context to pass to `getPaymasterData` and `getPaymasterStubData` calls. */
paymasterContext?: unknown | undefined
} & OneOf<
| {
context: Hex
}
| {
initData: Hex
}
>

export async function installModule<
TSmartAccount extends SmartAccount | undefined
Expand All @@ -37,7 +58,12 @@ export async function installModule<
maxPriorityFeePerGas,
nonce,
address,
context
context,
initData,
type,
calls,
paymaster,
paymasterContext
} = parameters

if (!account_) {
Expand All @@ -54,41 +80,14 @@ export async function installModule<
"sendUserOperation"
)({
calls: [
{
to: account.address,
value: BigInt(0),
data: encodeFunctionData({
abi: [
{
name: "installModule",
type: "function",
stateMutability: "nonpayable",
inputs: [
{
type: "uint256",
name: "moduleTypeId"
},
{
type: "address",
name: "module"
},
{
type: "bytes",
name: "initData"
}
],
outputs: []
}
],
functionName: "installModule",
args: [
parseModuleTypeId(parameters.type),
getAddress(address),
context
]
})
}
...encodeInstallModule({
account,
modules: [{ address, context: context ?? initData, type }]
}),
...(calls ?? [])
],
paymaster,
paymasterContext,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ describe.each(getCoreSmartAccounts())(

const opHash = await installModules(smartClient, {
account: smartClient.account,
calls: [
{
to: smartClient.account.address,
value: 0n,
data: "0x"
}
],
modules: [
{
type: "executor",
Expand Down
89 changes: 40 additions & 49 deletions packages/permissionless/actions/erc7579/installModules.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,41 @@
import type { Address, Chain, Client, Hex, Narrow, Transport } from "viem"
import {
type Address,
type Chain,
type Client,
type Hex,
type Transport,
encodeFunctionData,
getAddress
} from "viem"
import {
type GetSmartAccountParameter,
type PaymasterActions,
type SmartAccount,
type UserOperationCalls,
sendUserOperation
} from "viem/account-abstraction"
import { getAction, parseAccount } from "viem/utils"
import { AccountNotFoundError } from "../../errors"
import { type ModuleType, parseModuleTypeId } from "./supportsModule"
import {
type EncodeInstallModuleParameters,
encodeInstallModule
} from "../../utils/encodeInstallModule"

export type InstallModulesParameters<
TSmartAccount extends SmartAccount | undefined
> = GetSmartAccountParameter<TSmartAccount> & {
modules: {
type: ModuleType
address: Address
context: Hex
}[]
TSmartAccount extends SmartAccount | undefined,
calls extends readonly unknown[] = readonly unknown[]
> = EncodeInstallModuleParameters<TSmartAccount> & {
maxFeePerGas?: bigint
maxPriorityFeePerGas?: bigint
nonce?: bigint
calls?: UserOperationCalls<Narrow<calls>>
paymaster?:
| Address
| true
| {
/** Retrieves paymaster-related User Operation properties to be used for sending the User Operation. */
getPaymasterData?:
| PaymasterActions["getPaymasterData"]
| undefined
/** Retrieves paymaster-related User Operation properties to be used for gas estimation. */
getPaymasterStubData?:
| PaymasterActions["getPaymasterStubData"]
| undefined
}
| undefined
/** Paymaster context to pass to `getPaymasterData` and `getPaymasterStubData` calls. */
paymasterContext?: unknown | undefined
}

export async function installModules<
Expand All @@ -40,7 +49,10 @@ export async function installModules<
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
modules
modules,
paymaster,
paymasterContext,
calls
} = parameters

if (!account_) {
Expand All @@ -55,36 +67,15 @@ export async function installModules<
sendUserOperation,
"sendUserOperation"
)({
calls: modules.map(({ type, address, context }) => ({
to: account.address,
value: BigInt(0),
data: encodeFunctionData({
abi: [
{
name: "installModule",
type: "function",
stateMutability: "nonpayable",
inputs: [
{
type: "uint256",
name: "moduleTypeId"
},
{
type: "address",
name: "module"
},
{
type: "bytes",
name: "initData"
}
],
outputs: []
}
],
functionName: "installModule",
args: [parseModuleTypeId(type), getAddress(address), context]
})
})),
calls: [
...encodeInstallModule({
account,
modules
}),
...(calls ?? [])
],
paymaster,
paymasterContext,
maxFeePerGas,
maxPriorityFeePerGas,
nonce,
Expand Down
22 changes: 17 additions & 5 deletions packages/permissionless/actions/erc7579/isModuleInstalled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
type Client,
ContractFunctionExecutionError,
type Hex,
type OneOf,
type Transport,
decodeFunctionResult,
encodeFunctionData,
Expand All @@ -23,16 +24,27 @@
> = GetSmartAccountParameter<TSmartAccount> & {
type: ModuleType
address: Address
context: Hex
}
} & OneOf<
| {
additionalContext: Hex
}
| {
context: Hex
}
>

export async function isModuleInstalled<
TSmartAccount extends SmartAccount | undefined
>(
client: Client<Transport, Chain | undefined, TSmartAccount>,
parameters: IsModuleInstalledParameters<TSmartAccount>
): Promise<boolean> {
const { account: account_ = client.account, address, context } = parameters
const {
account: account_ = client.account,
address,
context,
additionalContext
} = parameters

if (!account_) {
throw new AccountNotFoundError({
Expand Down Expand Up @@ -82,7 +94,7 @@
args: [
parseModuleTypeId(parameters.type),
getAddress(address),
context
context ?? additionalContext
],
address: account.address
})
Expand All @@ -104,7 +116,7 @@
args: [
parseModuleTypeId(parameters.type),
getAddress(address),
context
context ?? additionalContext

Check warning on line 119 in packages/permissionless/actions/erc7579/isModuleInstalled.ts

View check run for this annotation

Codecov / codecov/patch

packages/permissionless/actions/erc7579/isModuleInstalled.ts#L119

Added line #L119 was not covered by tests
]
})
})
Expand Down
Loading
Loading