UNPKG

@zerodev/sdk

Version:

A utility library for working with ERC-4337

152 lines (141 loc) 4.66 kB
import { type Chain, type Client, type Hash, type Hex, type Prettify, type Transport, zeroAddress } from "viem" import { type SendUserOperationParameters, type SmartAccount, sendUserOperation } from "viem/account-abstraction" import { concatHex, encodeFunctionData, getAction, pad, parseAccount } from "viem/utils" import type { KernelSmartAccountImplementation } from "../../accounts/index.js" import { KernelV3_1AccountAbi } from "../../accounts/kernel/abi/kernel_v_3_1/KernelAccountAbi.js" import { KERNEL_V3_0, KERNEL_V3_1, KernelVersionToAddressesMap, VALIDATOR_TYPE } from "../../constants.js" import { AccountNotFoundError } from "../../errors/index.js" import type { KernelValidator, KernelValidatorHook } from "../../types/kernel.js" export type ChangeSudoValidatorParameters< account extends SmartAccount | undefined, accountOverride extends SmartAccount | undefined = undefined, calls extends readonly unknown[] = readonly unknown[] > = Prettify< Partial<SendUserOperationParameters<account, accountOverride, calls>> & { sudoValidator: KernelValidator<string> hook?: KernelValidatorHook } > export async function changeSudoValidator< account extends SmartAccount | undefined, chain extends Chain | undefined, accountOverride extends SmartAccount | undefined = undefined, calls extends readonly unknown[] = readonly unknown[] >( client: Client<Transport, chain, account>, args: Prettify< ChangeSudoValidatorParameters<account, accountOverride, calls> > ): Promise<Hash> { const { sudoValidator, hook, ...restArgs } = args const account_ = restArgs.account ?? client.account if (!account_) throw new AccountNotFoundError({ docsPath: "/docs/actions/wallet/sendTransaction" }) const account = parseAccount( account_ ) as unknown as SmartAccount<KernelSmartAccountImplementation> let rootValidatorId: Hex if ( [ VALIDATOR_TYPE.PERMISSION, VALIDATOR_TYPE.SECONDARY, VALIDATOR_TYPE.EIP7702 ].includes(VALIDATOR_TYPE[sudoValidator.validatorType]) ) { rootValidatorId = concatHex([ VALIDATOR_TYPE[sudoValidator.validatorType], pad(sudoValidator.getIdentifier(), { size: 20, dir: "right" }) ]) } else { throw new Error( `Cannot change sudo validator to type ${sudoValidator.validatorType}` ) } const validatorData = await sudoValidator.getEnableData(account.address) const hookId = hook?.getIdentifier() ?? zeroAddress const hookData = (await hook?.getEnableData(account.address)) ?? "0x" /** * @dev Kernel v3.0 does not support changeRootValidator directly, so we need to use delegatecall to call changeRootValidator on Kernel v3.1 implementation contract */ if (account.kernelVersion === KERNEL_V3_0) { return await getAction( client, sendUserOperation, "sendUserOperation" )({ ...restArgs, callData: await account.encodeCalls( [ { to: KernelVersionToAddressesMap[KERNEL_V3_1] .accountImplementationAddress, value: 0n, data: encodeFunctionData({ abi: KernelV3_1AccountAbi, functionName: "changeRootValidator", args: [ rootValidatorId, hookId, validatorData, hookData ] }) } ], "delegatecall" ) } as SendUserOperationParameters) } /** * @dev Kernel v3.1 supports changeRootValidator directly */ return await getAction( client, sendUserOperation, "sendUserOperation" )({ ...restArgs, callData: await account.encodeCalls([ { to: account.address, value: 0n, data: encodeFunctionData({ abi: KernelV3_1AccountAbi, functionName: "changeRootValidator", args: [rootValidatorId, hookId, validatorData, hookData] }) } ]) } as SendUserOperationParameters) }