v14.17.0 creates new SHHH wallets on V8.5, which fixes a threshold bypass in V8.4 (no mainnet wallet was affected). It also lets a user’s own Starknet wallet (Bramble, Braavos, Ready, or another Chipi wallet) become a co-owner or a recovery guardian of their Chipi wallet. The wallet keeps its key and approves with
wallet_signTypedData; Chipi relays gaslessly. It also fixes threshold signatures and Argent-shaped signatures. One behavior is stricter: a Chipi wallet object now refuses typed data with no chainId (see the table).TL;DR: does this affect me?
SHHH V8.5
Through V8.4 the SHHH account checked the threshold only on threshold envelopes (V2_THRESHOLD). Its single-owner envelope (V2_SNIP12) never read it, so on an N-of-M wallet one owner signing alone could execute. V8.5 requires that owner’s weight to meet the threshold, except for one call: an owner cancelling a recovery, naming itself. A guardian can still start a recovery alone, as before.
No mainnet wallet was affected: none ever had a threshold above 1. Full record: v8-5-audit-entry.md.
What changes for you:
createWallet(TS and Python) computes the address with V8.5 and now names that class inprepare-creation. If the API answers with any other class it stops withNot deploying, so a wallet can’t land at an address the SDK didn’t compute. The API keeps V8.4 as its default for older SDKs, which name no class.- Existing wallets don’t move. V8.x has no upgrade path, and a V8.4 wallet at threshold 1 (every V8.4 wallet on mainnet) is not affected.
getWalletTypeFromClassHashstill returnsSHHHfor V8.4. - N-of-M only on V8.5. Chipi’s API refuses
propose_set_threshold/execute_set_thresholdabove 1 for wallets on older classes (422 SHHH_THRESHOLD_UNSUPPORTED). A V8.4 treasury’srequiredApprovalsare enforced by Chipi’s backend only; to get the on-chain N-of-M, move it to a V8.5 wallet. See Co-signing. - Same API otherwise. V8.5 has the same constructor, storage layout and ABI as V8.4: every builder, hook and envelope works unchanged.
- Migrating CHIPI wallets to SHHH (
migrateChipiWalletToShhh) still upgrades them to V8.4, the class Chipi’s migration names.
Trusted wallets (@chipi-stack/backend, chipi-react, nextjs)
Bramble signs with a STARK key, but only through typed data that includes its own address, so the wallet’s STARK signer can’t check it. The new STARK_SNIP12 signer kind checks the STARK signature over an Approval { Wallet, Hash } typed data instead.
starkSnip12ApprovalTypedData,resolveStarkSnip12Signer,starkSnip12PubkeyFelts,buildStarkSnip12Envelope,verifyStarkSnip12Approval,parseStarknetWalletSignature.sdk.executeWithExternalSigneranduseExternalSignerExecute: run calls approved by the external wallet, relayed gaslessly. Lower level:prepareExternalOwnerExecution/submitExternalOwnerExecution.- Governance:
buildProposeAddVerifierClassCall/buildExecuteAddVerifierClassCall(a wallet must register a kind before it can have an owner of that kind),isShhhVerifierDeclared. - Reads:
readShhhOwners,readVerifierClass,readPendingRecovery,parseOpProposedEvents(op ids come from the propose transaction’s events). executeShhhWithStarkKey: sign as a STARK owner other than owner 0, such as the key a guardian recovery added.
StarkSnip12Verifier, class 0x017884125977631bee198b34cd3e3fcf975a543e453c8b996a818910a964b5e) lands on existing wallets through propose_add_verifier_class (48 hours); no wallet redeploys or upgrades. It is declared on mainnet (2026-10-14, block 16377651).
Connect with Chipi 0.5.0 (@chipi-stack/starknet-connector)
Wallet scanners such as get-starknet v4 call wallet_getPermissions on every injected wallet at page load, Bramble’s and Chipi’s alike. Those passive calls no longer try to open the Chipi popup: before the user connects, Chipi answers them locally. The README and connector docs now show Chipi next to Bramble, Ready and Braavos, and list every error the connector returns.
Connect with Chipi wallet object (@chipi-stack/chipi-react)
useChipiWalletObject answered wallet_deploymentData with 115 (“already deployed”) even for an account that is not deployed. It now answers 116 (“deployment data is not available”) unless you pass isDeployed: true, which keeps 115.
Fixes
- Threshold envelopes (
@chipi-stack/backend, Python SDK):buildThresholdEnvelopekept each owner’sV2_SNIP12tag inside the envelope, and the wallet contract rejected every such envelope withTHRESH: bad owner_id. It now emits each frame as[owner_id, kind_tag, ...payload], the shape the contract verifies.useThresholdSigngets the fix through it; you still pass the per-kind builders’ envelopes. - Argent signatures: the paymaster adapter (
sendSponsored()) and core’s x402 client read["1", "0", publicKey, r, s]asr = 1, s = 0. Both now takerandsfrom the end, and refuse shapes they don’t know. - Sign in with Starknet accepts the domain
chainIdasSN_MAINor its felt.
Docs fixes
- Guardian recovery: recovery adds an owner (it never replaces one),
cancel_recoverytakes the cancelling owner’s id, guardians cannot cancel, and everyexecute_*call is permissionless. Adding an owner of a new kind needs the verifier class first. - Sign in with Starknet: Bramble end to end, every failure reason, and the wallet error codes.
- When passkeys fail, threshold, multi-owner governance and the core signer pages: corrected against the code.
