Hackathon Project • Resolve Starknet 2025 WINNER
Build once, run anywhere: session keys • guardians • paymasters for Starknet AA.
Starknet is account-abstraction by default, but today AA features are fragmented across wallets, blog posts, and vendor SDKs.
UA²-SDK unifies them into a modular Cairo account + TypeScript SDK:
- 🔑 Session Keys — scoped, expiring, revocable
- 🛡️ Guardians & Recovery — m-of-n social recovery with timelock
- ♻️ Key Rotation — secure ownership change
- ⛽ Paymaster Adapters — plug in any sponsor provider, gasless or alt-token
- 🧩 Wallet-agnostic — Argent, Braavos, Cartridge, injected
Goal: Make Starknet AA features usable today by any dApp, game, or protocol.
- On-chain: UA² Account contract (inherits OZ AccountComponent)
- Modules: SessionKeys, Guardians, KeyRotation
- Off-chain: TypeScript SDK (
@ua2/core,@ua2/react,@ua2/paymasters) - Demo app: React front-end + CLI showing end-to-end flows
See docs/architecture.md for diagrams and flow details.
cp .env.example .env
cp .env.sepolia.example .env.sepoliaUpdate the copied files with your local devnet defaults (
.env) and Sepolia RPC + UA² addresses (.env.sepolia).
npm cicd packages/contracts
scarb buildTip
The repo pins scarb 2.12.0 via .tool-versions and expects it to be provided by
mise. If scarb is not on your PATH, install the pinned version with
mise install scarb@2.12.0 (or ensure /root/.asdf/shims is exported when using asdf).
Mirror the same workflow locally and on Sepolia so copy/pasting always works. Replace the
placeholders (<...>) before running.
# still inside packages/contracts
# Devnet example (see docs/runbook-sepolia.md for full flow)
RPC=http://127.0.0.1:5050
NAME=devnet
sncast account create --name "$NAME" --url "$RPC"
sncast account deploy --name "$NAME" --url "$RPC"
sncast --account "$NAME" \
declare \
--contract-name UA2Account \
--url "$RPC" \
--max-fee 9638049920000000000
UA2_CLASS_HASH=0xCLASS_HASH_FROM_OUTPUT
OWNER_PUBKEY=0xYOUR_OWNER_FELT
sncast --account "$NAME" \
deploy \
--class-hash "$UA2_CLASS_HASH" \
--constructor-calldata "$OWNER_PUBKEY" \
--url "$RPC" \
--max-fee 9638049920000000000
UA2_PROXY_ADDR=0xDEPLOYED_ADDRESS
sncast --account "$NAME" \
call \
--contract-address "$UA2_PROXY_ADDR" \
--function get_owner \
--url "$RPC"
# Sepolia mirrors the same steps; just switch RPC/NAME and fund the account with STRK (FRI)
RPC=https://starknet-sepolia.infura.io/v3/<YOUR_KEY>
NAME=sepoliaIf sncast reports "fee too low", rerun the declare/deploy with the suggested higher
--max-fee (fees are denominated in FRI (STRK)). Copy the resulting class hash,
implementation hash, and proxy address into .env / .env.sepolia so the SDK and demo app
point at the correct contracts. ./scripts/deploy_ua2.sh is still available when you want an
automated run.
Note
On devnet, mint FRI to the printed account address via devnet_mint. On Sepolia,
top up the account with STRK/ETH from your faucet or bridge of choice before
deploying.
-
Cairo unit tests:
cd packages/contracts snforge test -vv
[!NOTE] The setup script installs
snforgevia theasdfstarknet-foundryplugin. Export theasdfshims directory (e.g.~/.asdf/shims) to yourPATH, or call the binary directly from the install root (e.g.~/.asdf/installs/starknet-foundry/0.48.1/bin/snforge) if the command is not found. -
TS/SDK tests:
npm run test:unit
For reviewers who want to watch the interactive sncast + curl flow, we keep the repo-local
run.sh. It walks through account creation, funding, deployment, and the session-key happy/
sad-path calls while teeing all output into ua2_e2e_demo.log.
- Prereqs: Starknet devnet running at
http://127.0.0.1:5050, the UA² class declared, andsncast≥ 0.50.0 available on yourPATH(pluscurl,jq,node,date). - Export the values the script needs:
export UA2_CLASS_HASH=0x... export UA2_DEVNET_OWNER_PRIVATE_KEY=0x... # 32B hex private key you control on devnet export TARGET_ADDRESS=0x... # e.g. mock ERC20 you want to permit export UA2_NAME=ua2 # optional; defaults to "ua2" export RPC=http://127.0.0.1:5050 # optional; defaults to devnet URL above
- If you want a clean slate, delete the prior account/profile first:
sncast account delete --name "${UA2_NAME:-ua2}" - Run the walkthrough:
The pauses will prompt in interactive terminals; in CI/non-TTY contexts they auto-advance with a short delay. Step three now mints FRI (STRK) by default so deployments succeed on the latest devnet builds.
./run.sh
- Inspect
ua2_e2e_demo.logfor the captured transcript, including the expectedERR_POLICY_CALLCAPrevert on the final session call.
Coverage and case mapping: docs/test-plan.md
Threat model: docs/threat-model.md
Highlights:
- Domain-separated session signatures
- Hard expiries and call/value caps
- Guardian quorum + timelock recovery
- Events for every state change
- Proxy upgrade separation + pause switch
- RFC (high-level spec)
- Architecture Overview
- Interfaces
- Validation Logic
- Runbook (Sepolia)
- Test Plan
- Threat Model
- SDK API Reference
- Demo Script
- ADRs (Design Records)
- Roadmap
- Connect & deploy UA² Account
- Create session (transfer cap)
- Use session (no wallet popup)
- Policy violation → revert
- Sponsored tx → succeed
- Revoke → fail
- Guardian recovery → owner rotated
Details: docs/demo-script.md
- v0.2: bitmap allowlists, policy templates, extra paymasters
- v0.3: WebAuthn session keys, multisig owners, more wallets
- v0.4: formal verification, gas benchmarking, Python/Rust SDKs
Full plan: docs/roadmap.md
Contributions welcome!
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
Apache-2.0. See LICENSE.