On-Chain Trust Enforcement Protocol for Solana
Custodio.dev is a Solana-native protocol that assigns wallets a TrustTier (0–5) based on reputation signals and enforces permissions on-chain (not in UI).
Program ID (Devnet): 7jE8RH9vYxj44H45qvvSnG5TYoEDNsMcexeQwrxBoDHs
- On-chain TrustTier system (0–5) - Stored per-wallet in PDAs
- Time-based decay - Inactive wallets lose trust automatically
assert_permissioninstruction - Fails transactions if tier is insufficient- Deployed devnet program - Fully functional on Solana devnet
- HTTP API with API key protection - For non-Solana developers
- Vercel-compatible backend - Deploy with
npx vercel - FairScale integration (optional) - Fetch external reputation scores
- Oracle verification of scores - Users can self-report scores (demo limitation)
- Frontend UI - Out of scope for this submission
- ZK proofs - Design document only (
docs/zk.md) - Rate limiting / database - Kept simple for hackathon
┌─────────────────────────────────────────────────────────────────┐
│ Custodio.dev │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ FairScale │───▶│ Backend │───▶│ Solana Program │ │
│ │ (optional) │ │ HTTP API │ │ (Anchor) │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Read-only │ │ UserState │ │
│ │ permission │ │ PDA with │ │
│ │ check │ │ TrustTier │ │
│ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Key insight: The HTTP API is read-only. It reads on-chain state to check permissions. Writing to chain (init_user, update_tier) requires Solana transactions.
curl -X POST https://your-api.vercel.app/api/check-permission \
-H "Authorization: Bearer cust_test_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"wallet": "6cxXezcWW2cFCdE18qTAqLegZGL3mtXuE8ydshXsbXB4",
"requiredTier": 3
}'Response:
{
"allowed": false,
"currentTier": 0,
"tierName": "Untrusted",
"effectiveScore": 0,
"requiredTier": 3,
"reason": "Tier 0 is below required tier 3",
"meta": {
"source": "on-chain",
"program": "7jE8RH9vYxj44H45qvvSnG5TYoEDNsMcexeQwrxBoDHs",
"network": "devnet"
}
}cd backend
npm install
npx vercel
# Set environment variable: CUSTODIO_API_KEYS=cust_test_demo123456anchor build
anchor test --skip-local-validator| Score Range | TrustTier | Meaning |
|---|---|---|
| ≤ 400 | 0 | Untrusted / New |
| 401 – 600 | 1 | Basic trust |
| 601 – 800 | 2 | Moderate trust |
| 801 – 900 | 3 | Good standing |
| 901 – 950 | 4 | High trust |
| 951 – 1000 | 5 | Maximum trust |
Inactive wallets automatically lose trust:
| Inactivity | Decay Factor | Effective Score |
|---|---|---|
| ≤ 3 days | 100% | No change |
| 4–7 days | 90% | 900 → 810 |
| 8–14 days | 75% | 900 → 675 |
| 15–30 days | 50% | 900 → 450 |
| > 30 days | 25% | 900 → 225 |
The assert_permission instruction is the core innovation:
pub fn vote(ctx: Context<Vote>) -> Result<()> {
// Transaction FAILS if tier < 3
assert_permission(&ctx.accounts.user_state, 3)?;
// Only reaches here if tier >= 3
Ok(())
}Why this matters: Permission is enforced at the program level. Users cannot bypass it by calling RPC directly.
custodio.dev/
├── contracts/ # On-chain Solana program
│ ├── custodio/src/
│ │ ├── lib.rs # 4 instructions
│ │ ├── state.rs # UserState PDA (92 bytes)
│ │ ├── constants.rs # Tier thresholds, decay
│ │ ├── utils.rs # compute_tier(), apply_decay()
│ │ └── instructions/ # init_user, update_tier, etc.
│ └── tests/custodio.ts # Anchor tests
│
├── backend/ # HTTP API (Vercel-ready)
│ ├── app/api/
│ │ ├── check-permission/ # POST - main endpoint
│ │ └── health/ # GET - health check
│ └── lib/
│ ├── auth.ts # API key validation
│ ├── solana.ts # On-chain reader
│ └── fairscale.ts # FairScale integration
│
├── docs/zk.md # ZK extension design (future)
├── Anchor.toml
├── Cargo.toml
└── README.md
# Required
CUSTODIO_API_KEYS=cust_test_key1,cust_live_key2
# Optional
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_NETWORK=devnet
FAIRSCALE_API_KEY=your_fairscale_key# Build program
anchor build
# Run tests on devnet
anchor test --skip-local-validatorTest coverage:
init_user- Creates UserState PDAupdate_tier- Score → tier mappingassert_permission- Rejects insufficient tier
Check if a wallet meets a tier requirement.
Headers:
Authorization: Bearer <API_KEY>(required)Content-Type: application/json
Body:
{
"wallet": "base58-address",
"requiredTier": 3,
"includeFairScale": false
}Response:
{
"allowed": true,
"currentTier": 4,
"tierName": "High",
"effectiveScore": 920,
"requiredTier": 3
}Health check. Returns Solana connection status.
- On-chain is truth - The API reads from blockchain, not a database
- API keys are secrets - Never expose in frontend code
- Score source is NOT verified - This is a known demo limitation
MIT License - See LICENSE
Built for the FairScale Solana Build Bounty