ZeroDev ECDSA Validator signature error with CDP toViemAccount
Resolved 💬 2 comments Opened Dec 30, 2025 by cmichaeltimmons Closed Dec 30, 2025
Description
When using toViemAccount from @coinbase/cdp-core as a signer for ZeroDev's ECDSA validator, user operations fail with an AA24 signature error.
Environment
@coinbase/cdp-core: 0.0.74@coinbase/cdp-hooks: 0.0.74@zerodev/sdk: latest@zerodev/ecdsa-validator: latest- Chain: Base Mainnet (8453)
- EntryPoint: 0.7
- Kernel Version: KERNEL_V3_1
Steps to Reproduce
- Create a CDP account using
@coinbase/cdp-hooks - Get the EOA address from
currentUser.evmAccounts[0] - Create a viem account using
toViemAccount(eoaAddress) - Pass this account to ZeroDev's
signerToEcdsaValidator - Create a kernel account and client
- Send a user operation
Code
import { toViemAccount } from "@coinbase/cdp-core"
import { signerToEcdsaValidator } from "@zerodev/ecdsa-validator"
import { createKernelAccount, createKernelAccountClient } from "@zerodev/sdk"
import { getEntryPoint, KERNEL_V3_1 } from "@zerodev/sdk/constants"
const eoaAddress = currentUser?.evmAccounts?.[0]
const cdpAccount = await toViemAccount(eoaAddress)
const validator = await signerToEcdsaValidator(publicClient, {
signer: cdpAccount,
entryPoint: getEntryPoint("0.7"),
kernelVersion: KERNEL_V3_1,
})
const kernelAccount = await createKernelAccount(publicClient, {
plugins: { sudo: validator },
entryPoint,
kernelVersion,
})
const kernelClient = await createKernelAccountClient({
account: kernelAccount,
chain: base,
bundlerTransport: http(rpcUrl),
client: publicClient,
paymaster: { /* ... */ },
})
// This fails with AA24 signature error
const userOpHash = await kernelClient.sendUserOperation({ calls: [...] })
Error
UserOperationExecutionError: Signature provided for the User Operation is invalid.
This could arise when:
- the `signature` for the User Operation is incorrectly computed, and unable to be verified by the Smart Account
Details: UserOperation reverted with reason: AA24 signature error
Console Output
The toViemAccount returns a valid-looking LocalAccount:
{
address: "0xEE975f934109002E2D4b3EaeBDed4126949Ca30f",
nonceManager: undefined,
sign: ƒ async sign(e28),
signAuthorization: undefined,
signMessage: ƒ async signMessage({ message: e28 }),
signTransaction: ƒ async signTransaction(e28),
signTypedData: ƒ async signTypedData(e28),
source: "custom",
type: "local"
}
Observations
- The EOA address (
0xEE975...) is correctly embedded in the factory data - The signature is being generated but fails verification on-chain
- This suggests a potential mismatch in signature format between what CDP produces and what ZeroDev/Kernel expects
Possible Causes
- EIP-191 vs EIP-712 signature format mismatch
- Missing signature prefix or encoding differences
- Hash computation differences between CDP signing and what ZeroDev expects for UserOp signing
Questions
- Does
toViemAccountproduce signatures compatible with ERC-4337 UserOperation signing? - Is there a specific signature format or encoding that ZeroDev's ECDSA validator expects?
- Are there any known compatibility issues between CDP's signing and account abstraction validators?
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗