Bitcoin-native stablecoin protocol powered by zero-knowledge proofs via Charms
Built for the Charms Hackathon - demonstrating programmable assets on Bitcoin
zkUSD is a fully decentralized USD-pegged stablecoin running natively on Bitcoin using the Charms Protocol. Users mint zkUSD by depositing BTC as collateral, creating Collateralized Debt Positions (CDPs) validated by zero-knowledge proofs.
- Native to Bitcoin - No bridges, no wrapped tokens, no custodians
- UTXO-Based - Each vault is an individual UTXO with its own state
- ZK-Verified - All state transitions proven with recursive zero-knowledge proofs
- Client-Side Validation - Inspired by RGB protocol, validated locally
All contracts are deployed and operational on Bitcoin Testnet4:
| Contract | App ID | Status |
|---|---|---|
| Price Oracle V2 | ee779405f88f890c... |
✅ Live |
| zkUSD Token V8 | a2a55bf313100167... |
✅ Live |
| Stability Pool V5 | b9412ca5d8ed6ca3... |
✅ Live |
| Vault Manager V6 | e6564c00d5ea8cb8... |
✅ Live |
Explorer Links:
First zkUSD Minted:
Standard Bitcoin explorers (mempool.space) only show BTC amounts. Charms data is embedded in the
OP_RETURNoutput as a ZK-proven spell - invisible to traditional explorers but fully verifiable.
The first mint transaction (f5a19de4...) contains 8 outputs:
| Output | Content | Charms Data |
|---|---|---|
0 |
VaultManager State | Protocol: 1 active vault, 500k sats total collateral |
1 |
Vault NFT | Owner vault: 500k sats collateral, 12 zkUSD debt |
2 |
Token State | total_supply: 1,000,000,000 (10 zkUSD) |
3 |
zkUSD Balance | 10 zkUSD (1,000,000,000 base units) |
4 |
BTC Change | Remaining BTC |
5 |
Commit Output | Charms protocol anchor |
6 |
OP_RETURN | Spell data (CBOR-encoded state + ZK proof) |
7 |
Fee Change | Transaction fees |
ZK Proof Verification (all 3 app contracts validated):
✅ app contract satisfied: n/a2a55bf3.../395ceff8... (Token NFT state)
✅ app contract satisfied: n/e6564c00.../5d4f8232... (VaultManager)
✅ app contract satisfied: t/a2a55bf3.../395ceff8... (zkUSD fungible - 10 zkUSD minted)
To verify locally with Charms CLI:
charms spell check --spell-json <spell.json> --prev-txs <txs.json>- Node.js 18+
- pnpm 8+
- Rust (for contract development)
# Clone the repository
git clone https://github.com/AndeLabs/zkusd-protocol.git
cd zkusd-protocol
# Install dependencies
pnpm install
# Start development server
pnpm devCreate .env.local in apps/web/:
NEXT_PUBLIC_NETWORK=testnet4
NEXT_PUBLIC_DEMO_MODE=false
NEXT_PUBLIC_PROVER_URL=https://v9.charms.dev/spells/provezkUSD Protocol
├── contracts/ # Charms Apps (Rust → WASM)
│ ├── price-oracle/ # BTC/USD price feed
│ ├── zkusd-token/ # Fungible stablecoin
│ ├── vault-manager/ # CDP management
│ ├── stability-pool/ # Liquidation pool
│ └── common/ # Shared types & logic
│
├── packages/
│ ├── sdk/ # TypeScript SDK
│ ├── config/ # Network configurations
│ ├── types/ # Shared types
│ └── utils/ # Utilities
│
└── apps/web/ # Next.js Frontend
Each contract is a Charms app compiled to WASM and deployed on Bitcoin:
- App Reference:
n/{app_id}/{vk}(NFTs) ort/{app_id}/{vk}(Fungible) - State Storage: UTXO charm data validated by ZK proofs
- Cross-App Calls: Contracts reference each other via
app_id - Atomicity: All operations in a single Bitcoin transaction (spell)
Token.authorized_minter → VaultManager.app_id
VaultManager.zkusd_token_id → Token.app_id
VaultManager.oracle_id → PriceOracle.app_id
StabilityPool.vm_id → VaultManager.app_id
- Deposit BTC as collateral
- Mint zkUSD with 110% minimum collateral ratio
- Adjust position anytime
- Earn BTC rewards by providing zkUSD liquidity
- Automatic liquidation processing
- Fair distribution of liquidation gains
- Underwater vaults (< 110% CR) can be liquidated
- Stability Pool absorbs bad debt
- Liquidators receive collateral bonus
- Exchange zkUSD for BTC at face value
- 0.5% minimum fee
- Redeems from riskiest vaults first
| Parameter | Value |
|---|---|
| Minimum Collateral Ratio | 110% |
| Critical Collateral Ratio | 150% |
| Minimum Debt | 10 zkUSD |
| Opening Fee | 0.5% + base rate |
| Liquidation Bonus | 0.5% |
| Redemption Fee Floor | 0.5% |
# Development
pnpm dev # Start web app
pnpm build # Build all packages
pnpm typecheck # Type checking
pnpm lint # Linting
pnpm test # Run tests
# Contracts (requires Rust + Charms CLI)
cd contracts/vault-manager
charms app build # Build WASM (uses wasm32-wasip1)
charms app vk <wasm> # Get verification keyCRITICAL: Always use
charms app build- it uses the correctwasm32-wasip1target.
# Correct way
cd contracts/stability-pool
charms app build
# NEVER use (causes runtime errors)
cargo build --target wasm32-unknown-unknownSee contracts/BUILDING.md for details.
- Language: Rust
- Target: WASM32-WASIP1 (Charms runtime)
- SDK:
charms-sdkv0.11+ - Serialization: Borsh, Serde CBOR
- Framework: Next.js 15, React 19
- Styling: TailwindCSS
- State: Zustand
- Wallet: Unisat, Xverse integration
- Monorepo: Turborepo + pnpm
- Testing: Vitest
- Prover: Charms ZK Prover API
Unlike Ethereum flash loans, zkUSD flash mints are atomically validated in a single UTXO transaction:
pub struct FlashMint {
pub amount: u64, // Amount to mint
pub fee: u64, // 0.05% fee
pub purpose: Purpose, // SelfLiquidation, Arbitrage, etc.
}Third parties can rescue underwater vaults without owner permission:
pub struct Rescue {
pub vault_id: VaultId,
pub collateral_to_add: u64,
pub debt_to_repay: u64,
pub rescuer_discount: u64, // Max 5%
}Liquidation protection as transferable NFT charms:
pub struct Insurance {
pub coverage_btc: u64,
pub trigger_icr: u64, // Auto-triggers below this
pub expires_at: u64,
}| Feature | MakerDAO | Liquity | zkUSD |
|---|---|---|---|
| Native Bitcoin | ❌ | ❌ | ✅ |
| UTXO-based | ❌ | ❌ | ✅ |
| Flash mints | ✅ (callbacks) | ❌ | ✅ (atomic) |
| Atomic rescue | ❌ | ❌ | ✅ |
| Insurance NFTs | ❌ | ❌ | ✅ |
| No re-entrancy | ❌ | ❌ | ✅ |
.
├── apps/
│ └── web/ # Next.js frontend
├── contracts/
│ ├── common/ # Shared Rust code
│ ├── price-oracle/ # Oracle contract
│ ├── stability-pool/ # Pool contract
│ ├── vault-manager/ # Vault contract
│ └── zkusd-token/ # Token contract
├── packages/
│ ├── config/ # Network configs
│ ├── sdk/ # TypeScript SDK
│ ├── types/ # Shared types
│ └── utils/ # Utilities
├── deployments/
│ └── testnet4/ # Deployment configs
├── scripts/ # Deployment scripts
└── spells/ # Spell templates
Phase 1 (Complete)
- ✅ Core CDP system
- ✅ Stability Pool
- ✅ Liquidations
- ✅ Testnet deployment
- ✅ Web UI
Phase 2 (Next)
- 🔄 Flash mint UI
- 🔄 Atomic rescue interface
- 🔄 Insurance marketplace
- 🔄 Redemption mechanism
Phase 3 (Future)
- 📊 Analytics dashboard
- 🤖 Liquidation bots
- 🌉 Cross-chain (Cardano, Dogecoin via Charms)
- 💱 AMM integration
- Fork the repository
- Create feature branch (
git checkout -b feature/amazing) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing) - Open Pull Request
MIT - See LICENSE
Built with ❤️ for the Charms Ecosystem
Demonstrating that Bitcoin can be a foundation for sophisticated DeFi applications through programmable assets. ]]>