diff --git a/apps/wallet/src/lib/eerc.shield.test.ts b/apps/wallet/src/lib/eerc.shield.test.ts index 34f7d7e..a4a6e89 100644 --- a/apps/wallet/src/lib/eerc.shield.test.ts +++ b/apps/wallet/src/lib/eerc.shield.test.ts @@ -19,6 +19,7 @@ const eercMocks = vi.hoisted(() => { const withdraw = vi.fn(); const transfer = vi.fn(); const calculateTotalBalance = vi.fn(); + const generateDecryptionKey = vi.fn(async () => `0x${"a".repeat(64)}`); class MockEERC { client = publicClient; @@ -29,6 +30,7 @@ const eercMocks = vi.hoisted(() => { withdraw = withdraw; transfer = transfer; calculateTotalBalance = calculateTotalBalance; + generateDecryptionKey = generateDecryptionKey; } return { @@ -36,6 +38,7 @@ const eercMocks = vi.hoisted(() => { calculateTotalBalance, deposit, fetchPublicKey, + generateDecryptionKey, publicClient, register, transfer, diff --git a/apps/wallet/src/lib/eerc.ts b/apps/wallet/src/lib/eerc.ts index aaea8cc..feeacfa 100644 --- a/apps/wallet/src/lib/eerc.ts +++ b/apps/wallet/src/lib/eerc.ts @@ -123,7 +123,7 @@ export async function createEerc(account: BenzoAccount): Promise { if (!ENCRYPTED_ERC_ADDRESS || !REGISTRAR_ADDRESS) return null; const EERCClass = await loadEERC(); const { publicClient, walletClient } = createViemClients(account); - return new EERCClass( + const eerc = new EERCClass( publicClient, walletClient, ENCRYPTED_ERC_ADDRESS, @@ -132,6 +132,17 @@ export async function createEerc(account: BenzoAccount): Promise { EERC_CIRCUIT_URLS, account.eercDecryptionKey, ); + // The eERC SDK does NOT use the `decryptionKey` we pass to the constructor for + // anything that touches chain state: register() derives its OWN key via + // generateDecryptionKey() (a deterministic wallet signature) and binds the + // on-chain public key + ElGamal-encrypted balance to THAT key. If we then + // decrypt with our own `account.eercDecryptionKey`, calculateTotalBalance()'s + // eGCT verify fails and every private balance reads $0. So let the SDK derive + // and install its own key (and matching publicKey) up front — the signature is + // local (self-custody key) and deterministic, so it's stable across sessions + // and matches whatever key registration used. + await eerc.generateDecryptionKey(); + return eerc; } function eercPublicClient(eerc: EERC): PublicClient {