Hello,
I am trying to use the Biconomy Smart Account with a custom module for passkey validation (not mentioned in the docs, but found here). I am not using any SDK and have deployed the PasskeyRegistryModule.sol contract myself.
This is how I populate the userOp:
export const BiconomyInitAbi = [
{
inputs: [
{
internalType: "address",
name: "handler",
type: "address",
},
{
internalType: "address",
name: "moduleSetupContract",
type: "address",
},
{
internalType: "bytes",
name: "moduleSetupData",
type: "bytes",
},
],
name: "init",
outputs: [
{
internalType: "address",
name: "",
type: "address",
},
],
stateMutability: "nonpayable",
type: "function",
},
{
inputs: [
{
internalType: "uint256",
name: "_pubKeyX",
type: "uint256",
},
{
internalType: "uint256",
name: "_pubKeyY",
type: "uint256",
},
{
internalType: "string",
name: "_keyId",
type: "string",
},
],
name: "initForSmartAccount",
outputs: [
{
internalType: "address",
name: "",
type: "address",
},
],
stateMutability: "nonpayable",
type: "function",
},
];
export const createAccountAbi = [
{
inputs: [
{
internalType: "address",
name: "moduleSetupContract",
type: "address",
},
{
internalType: "bytes",
name: "moduleSetupData",
type: "bytes",
},
{
internalType: "uint256",
name: "index",
type: "uint256",
},
],
name: "deployCounterFactualAccount",
outputs: [
{
internalType: "address",
name: "proxy",
type: "address",
},
],
stateMutability: "nonpayable",
type: "function",
},
];
const getPasskeyInitData = () => {
return encodeFunctionData({
abi: BiconomyInitAbi,
functionName: "initForSmartAccount",
args: [_pubKeyX, _pubKeyY, _keyId],
});
};
const getInitCode = () => {
const passkeyInitData = getPasskeyInitData();
const createAccountData = encodeFunctionData({
abi: createAccountAbi,
functionName: "deployCounterFactualAccount",
args: [PASSKEY_MODULE_ADDRESS, passkeyInitData, INDEX],
});
return concatHex([FACTORY_ADDRESS, createAccountData as Hex]);
};
const getAccountAddress = () => {
const passkeyInitData = getPasskeyInitData();
const initialisationData = encodeFunctionData({
abi: BiconomyInitAbi,
functionName: "init",
args: [FALLBACK_HANDLER_ADDRESS, PASSKEY_MODULE_ADDRESS, passkeyInitData],
});
const deploymentCode = encodePacked(
["bytes", "uint256"],
[BICONOMY_PROXY_CREATION_CODE, hexToBigInt(ACCOUNT_V2_0_LOGIC)],
);
const salt = keccak256(
encodePacked(
["bytes32", "uint256"],
[keccak256(encodePacked(["bytes"], [initialisationData])), INDEX],
),
);
return getContractAddress({
from: FACTORY_ADDRESS,
salt,
bytecode: deploymentCode,
opcode: "CREATE2",
});
};
const getDummySignature = () => {
const dynamicPart = PASSKEY_MODULE_ADDRESS.substring(2).padEnd(40, "0");
return `0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000${dynamicPart}000000000000000000000000000000000000000000000000000000000000004181d4b4981670cb18f99f0b4a66446df1bf5b204d24cfcb659bf38ba27a4359b5711649ec2423c5e1247245eba2964679b6a1dbb85c992ae40b9b00c6935b02ff1b00000000000000000000000000000000000000000000000000000000000000`;
};
I get the “-32500 AA23 reverted (or OOG)” error when trying to send the userOp to the Biconomy Paymaster. I am mostly confused by the dummy signature generation. I found this way to do it in the permissionless.js library, and it works for Biconomy Smart Accounts with the default ECDSA module. Am I doing something wrong, missing any steps, or is it simply not supposed to work this way? Thank you!