22
33## Problem Statement
44
5- The ** "Send with Paymaster (Passkey)"** button fails with AA23 error
6- (signature validation failure) during gas estimation, while:
5+ The ** "Send with Paymaster (Passkey)"** button fails with AA23 error (signature
6+ validation failure) during gas estimation, while:
77
8- - ✅ ** EOA + Paymaster** works correctly (confirmed: balance changed
9- 0.1 → 0.09 ETH)
8+ - ✅ ** EOA + Paymaster** works correctly (confirmed: balance changed 0.1 → 0.09
9+ ETH)
1010- ✅ ** Passkey without Paymaster** works correctly
1111- ✅ ** Rust integration test** with passkey + paymaster passes all assertions
1212- ❌ ** Vue button** with passkey + paymaster consistently fails with AA23
@@ -29,8 +29,8 @@ The **"Send with Paymaster (Passkey)"** button fails with AA23 error
2929 - This sets ` data: Bytes::default() ` (** empty bytes** , not a flow type)
3030- Calls ` passkey_send_transaction() ` which internally uses ` send_user_op() `
3131- Validates: sender only loses transfer amount (no gas fees paid by sender)
32- - ** Test assertion:** ` sender_delta == amount ` (only 1000 wei transferred,
33- no gas)
32+ - ** Test assertion:** ` sender_delta == amount ` (only 1000 wei transferred, no
33+ gas)
3434
3535## Failing Implementation: Vue Button
3636
@@ -69,8 +69,7 @@ AA23 reverted
6969
7070### Error Code Meaning
7171
72- - ** AA23** = Account's ` validateAccountSignature() ` reverted during
73- validation
72+ - ** AA23** = Account's ` validateAccountSignature() ` reverted during validation
7473- This is ** NOT** a paymaster error (which would be AA33)
7574- Occurs during gas estimation (` eth_call ` ) with state overrides
7675- Not during actual transaction submission
@@ -81,8 +80,8 @@ The AA23 error during gas estimation suggests one of these:
8180
82811 . ** Account state issue** : The passkey hasn't been registered properly or
8382 WebAuthn validator isn't installed as a module
84- 2 . ** Stub signature mismatch** : The stub signature used during gas
85- estimation doesn't match what the validator expects
83+ 2 . ** Stub signature mismatch** : The stub signature used during gas estimation
84+ doesn't match what the validator expects
86853 . ** Nonce state issue** : If account already used the passkey for other
8786 transactions, nonce validation might fail
88874 . ** State override problem** : The state override in the bundler's gas
@@ -178,8 +177,7 @@ in PaymasterParams constructor
178177- [ ] Deploy Account
179178- [ ] Fund Account (0.1 ETH)
180179- [ ] Load WebAuthn Validator Address
181- - [ ] Register Passkey (critical - installs WebAuthn validator
182- module)
180+ - [ ] Register Passkey (critical - installs WebAuthn validator module)
183181- [ ] Fund Paymaster (1 ETH)
184182- [ ] Verify Paymaster Balance shows > 0
185183
@@ -188,8 +186,7 @@ in PaymasterParams constructor
188186- ✅ Steps 1-5 complete successfully
189187- ✅ Console logs show addresses are loaded
190188- ❌ "Send with Paymaster (Passkey)" fails with AA23
191- - Error occurs during bundler's gas estimation (eth_call
192- simulateValidation)
189+ - Error occurs during bundler's gas estimation (eth_call simulateValidation)
193190
194191## Areas to Investigate
195192
@@ -246,14 +243,12 @@ The WebAuthnValidator might have specific requirements:
246243- Expected signature format (from ` stub_signature_passkey_core ` )
247244- Validation might fail if account state isn't properly simulated
248245- Validator code location:
249- `packages/erc4337-contracts/contracts/validators/
250- WebAuthnValidator.sol`
246+ ` packages/erc4337-contracts/contracts/validators/ WebAuthnValidator.sol `
251247
252248## WASM FFI Flow Details
253249
254250** File:**
255- `packages/sdk-platforms/rust/zksync-sso-erc4337/crates/
256- zksync-sso-erc4337-ffi-web/src/lib.rs`
251+ ` packages/sdk-platforms/rust/zksync-sso-erc4337/crates/ zksync-sso-erc4337-ffi-web/src/lib.rs `
257252
258253### Paymaster Normalization (lines 340-379)
259254
@@ -272,9 +267,8 @@ fn normalize_paymaster_params(pm: Option<PaymasterParams>) -> Option<PaymasterPa
272267}
273268```
274269
275- ** Note:** Hex decoding failures silently fall back to empty bytes.
276- This is why "0x05" vs null shouldn't matter, but might indicate other
277- issues.
270+ ** Note:** Hex decoding failures silently fall back to empty bytes. This is why
271+ "0x05" vs null shouldn't matter, but might indicate other issues.
278272
279273### UserOperation Preparation (lines 1186-1500)
280274
@@ -327,8 +321,7 @@ const balance = await publicClient.getBalance({
327321
328322### Anvil Logs
329323
330- Watch the Anvil terminal (Terminal "a") during "Send with Paymaster
331- (Passkey)":
324+ Watch the Anvil terminal (Terminal "a") during "Send with Paymaster (Passkey)":
332325
333326- Should show ` eth_call ` with state overrides
334327- Look for the account address in the calls
@@ -349,8 +342,7 @@ Check the bundler RPC calls in browser DevTools:
349342
350343### Hypothesis 1: Module Not Installed
351344
352- After clicking "Register Passkey", the WebAuthn validator should be
353- installed.
345+ After clicking "Register Passkey", the WebAuthn validator should be installed.
354346
355347** Test:**
356348
@@ -370,8 +362,7 @@ console.log("WebAuthn validator installed:", isInstalled)
370362
371363The passkey credentials might not be stored properly.
372364
373- ** Test:** Check the account's storage for passkey after "Register
374- Passkey":
365+ ** Test:** Check the account's storage for passkey after "Register Passkey":
375366
376367``` typescript
377368// Get account's passkey registry state
@@ -423,11 +414,11 @@ const paymaster = new PaymasterParams(paymasterAddress, null, null, null);
423414### Core Logic
424415
425416- [ lib.rs] (packages/sdk-platforms/rust/zksync-sso-erc4337/crates/
426- zksync-sso-erc4337-ffi-web/src/lib.rs) -
427- ` prepare_passkey_user_operation() ` , ` normalize_paymaster_params() `
417+ zksync-sso-erc4337-ffi-web/src/lib.rs) - ` prepare_passkey_user_operation() ` ,
418+ ` normalize_paymaster_params() `
428419- [ send.rs] (packages/sdk-platforms/rust/zksync-sso-erc4337/crates/
429- zksync-sso-erc4337-core/src/erc4337/account/modular_smart_account/
430- send.rs) - ` send_user_op() `
420+ zksync-sso-erc4337-core/src/erc4337/account/modular_smart_account/ send.rs) -
421+ ` send_user_op() `
431422- [ passkey.rs] (packages/sdk-platforms/rust/zksync-sso-erc4337/crates/
432423 zksync-sso-erc4337-core/src/erc4337/account/modular_smart_account/
433424 send/passkey.rs) - ` passkey_send_transaction() `
@@ -443,28 +434,32 @@ const paymaster = new PaymasterParams(paymasterAddress, null, null, null);
443434
444435- [ web-sdk-test.vue] ( examples/demo-app/pages/web-sdk-test.vue ) -
445436 ` sendWithPasskeyPaymaster() ` (line 1449)
446- - [ TransactionSender.vue] (examples/demo-app/components/
447- TransactionSender.vue) - Paymaster checkbox and submission
437+ - [ TransactionSender.vue] (examples/demo-app/components/ TransactionSender.vue) -
438+ Paymaster checkbox and submission
448439
449440## Next Steps for Debugging
450441
4514421 . ** Enable verbose logging:**
452- - Add ` console.log() ` statements in ` prepare_passkey_user_operation() `
453- (Rust WASM)
443+
444+ - Add ` console.log() ` statements in ` prepare_passkey_user_operation() ` (Rust
445+ WASM)
454446 - Log the prepared UserOperation before signing
455447 - Log the final paymaster field values
456448
4574492 . ** Test with reduced scope:**
450+
458451 - Try sending without paymaster to confirm passkey works
459452 - Try EOA with paymaster to confirm paymaster works
460453 - Combine both to identify interaction issue
461454
4624553 . ** Compare UserOperations:**
456+
463457 - Print full UserOp from working EOA + paymaster
464458 - Print full UserOp from failing Passkey + paymaster
465459 - Diff the two to find structural differences
466460
4674614 . ** Check state machine:**
462+
468463 - Ensure "Register Passkey" actually installed the module
469464 - Verify account state includes registered passkey
470465 - Confirm nonce is correct before sending
0 commit comments