Skip to content

Kernel Contracts: Support using already deployed contracts with different version #329

Description

@johanneskares

If you a deploy a Kernel contract (e.g. Version 0.2.2) and then try to verify a message while using a new version (e.g. 0.2.3) then the verification fails. The original Zerodev SDK supports this behaviour.

The Zerodev SDK uses accountMetadata to fetch the actual Kernel Version before signing
https://github.com/zerodevapp/sdk/blob/10839ec8d8fd2150c03af8362dc968adc516d324/packages/core/accounts/kernel/createKernelAccount.ts#L541

I created a PR, that fetches the actual Kernel version in a similar way, before signing the message:
#328

Here an example to replicate:

import { toEcdsaKernelSmartAccount } from "permissionless/accounts";
import { createPimlicoClient } from "permissionless/clients/pimlico";
import { http, type Hex, createPublicClient, getContract } from "viem";
import { entryPoint06Address } from "viem/account-abstraction";
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";

const privateKey = "0xprivatekey"
console.log("Test 0.2.2", await testKernel("0.2.2", true, privateKey));
console.log("Test 0.2.3", await testKernel("0.2.3", false, privateKey));

async function testKernel(version: "0.2.2" | "0.2.3" | "0.2.4", deployAccount: boolean, privateKey: Hex) {
	const publicClient = createPublicClient({
		chain: sepolia,
		transport: http(),
	});

	const apiKey = "pim_YOUR_API_KEY";

	const pimlicoUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}`;

	const owner = privateKeyToAccount(privateKey);

	const kernelAccount = await toEcdsaKernelSmartAccount({
		client: publicClient,
		entryPoint: {
			address: entryPoint06Address,
			version: "0.6",
		},
		version,
		owners: [owner],
	});

	const kernelAddress = kernelAccount.address;

	const result = await kernelAccount.signMessage({
		message: "Hello, world!",
	});

        if (deployAccount) {
            const pimlicoClient = createPimlicoClient({
		    transport: http(pimlicoUrl),
		    entryPoint: {
		    	address: entryPoint06Address,
			version: "0.6",
		    },
	    });

            const smartAccountClient = createSmartAccountClient({
                account: kernelAccount,
                chain: baseSepolia,
                paymaster: pimlicoClient,
                bundlerTransport: http(pimlicoUrl),
                userOperation: {
                    estimateFeesPerGas: async () =>
                        (await pimlicoClient.getUserOperationGasPrice()).fast
                }
            })
            
            const txHash = await smartAccountClient.sendTransaction({
                to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
                value: 1n
            })
        }

	return await publicClient.verifyMessage({
		address: kernelAddress,
		message: "Hello, world!",
		signature: result,
	});
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions