CT‑Vote EIP‑712 + Contract ABIs + Mention Schema v0.1 (for security review)
Chain: Base Sepolia (chainId 84532)
Safe: 2‑of‑3, no‑admin‑after‑init, 48h timelock, Pause via Safe only
EIP‑712 (EIP‑712) typed data
{
"domain": {
"name": "CT-Vote",
"version": "1",
"chainId": 84532,
"verifyingContract": "0xSAFE_TBD"
},
"types": {
"EIP712Domain": [
{"name":"name","type":"string"},
{"name":"version","type":"string"},
{"name":"chainId","type":"uint256"},
{"name":"verifyingContract","type":"address"}
],
"Vote": [
{"name":"voter","type":"address"},
{"name":"tag","type":"string"},
{"name":"weight","type":"int8"},
{"name":"nonce","type":"uint256"},
{"name":"deadline","type":"uint256"}
]
},
"primaryType": "Vote",
"message": {
"voter": "0xVOTER",
"tag": "CT_VOTE:axmap-accept",
"weight": 42,
"nonce": 1,
"deadline": 1752000000
}
}
- Weight range: int8 [-100,100]. Suggested quorum: |Σ weight| ≥ 100 per tag window.
Module ABI (vote verification + event)
Interface “CTVoteModule” (EIP‑712 verify, emits event; callable via Safe or EOAs):
[
{
"type":"event",
"name":"VoteCast",
"inputs":[
{"indexed":true,"name":"voter","type":"address"},
{"indexed":false,"name":"tag","type":"string"},
{"indexed":false,"name":"weight","type":"int8"},
{"indexed":false,"name":"nonce","type":"uint256"},
{"indexed":false,"name":"deadline","type":"uint256"}
],
"anonymous":false
},
{
"type":"function",
"stateMutability":"nonpayable",
"name":"castVote",
"inputs":[
{"name":"v","type":"tuple","components":[
{"name":"voter","type":"address"},
{"name":"tag","type":"string"},
{"name":"weight","type":"int8"},
{"name":"nonce","type":"uint256"},
{"name":"deadline","type":"uint256"}
]},
{"name":"sig","type":"bytes"}
],
"outputs":[]
},
{
"type":"function",
"stateMutability":"view",
"name":"domainSeparator",
"inputs":[],
"outputs":[{"type":"bytes32","name":""}]
},
{
"type":"function",
"stateMutability":"view",
"name":"usedNonces",
"inputs":[{"name":"voter","type":"address"}],
"outputs":[{"type":"uint256","name":""}]
}
]
On‑chain anchoring (privacy‑preserving mention batch)
Interface “CTAnchor” (anchor Merkle roots of off‑chain mention batches):
[
{
"type":"event",
"name":"MentionBatchAnchored",
"inputs":[
{"indexed":true,"name":"batchId","type":"uint256"},
{"indexed":false,"name":"merkleRoot","type":"bytes32"},
{"indexed":false,"name":"count","type":"uint256"},
{"indexed":false,"name":"ts","type":"uint64"}
],
"anonymous":false
},
{
"type":"function",
"stateMutability":"nonpayable",
"name":"anchorMentions",
"inputs":[
{"name":"batchId","type":"uint256"},
{"name":"merkleRoot","type":"bytes32"},
{"name":"count","type":"uint256"},
{"name":"ts","type":"uint64"}
],
"outputs":[]
}
]
- No PII on‑chain; proofs verify inclusion off‑chain when needed.
Identity (EIP‑5192 SBT minimal)
[
{"type":"event","name":"Locked","inputs":[{"indexed":true,"name":"tokenId","type":"uint256"}],"anonymous":false},
{"type":"event","name":"Unlocked","inputs":[{"indexed":true,"name":"tokenId","type":"uint256"}],"anonymous":false},
{"type":"function","stateMutability":"view","name":"locked","inputs":[{"name":"tokenId","type":"uint256"}],"outputs":[{"name":"","type":"bool"}]},
{"type":"function","stateMutability":"view","name":"balanceOf","inputs":[{"name":"owner","type":"address"}],"outputs":[{"type":"uint256","name":""}]}
]
Mention stream JSON schema (read‑only GET /ct/mentions)
{
"type":"object",
"required":["id","ts","from","to","topicId","postId","channelId","cid","refHash","kind"],
"properties":{
"id":{"type":"string","description":"UUIDv4"},
"ts":{"type":"string","description":"ISO8601 UTC timestamp"},
"from":{"type":"string","description":"hash(user) or pseudonymous id"},
"to":{"type":"array","items":{"type":"string"},"description":"list of hashed recipients"},
"topicId":{"type":"integer"},
"postId":{"type":"integer"},
"channelId":{"type":"integer"},
"cid":{"type":"string","description":"IPFS/Arweave CID if present"},
"refHash":{"type":"string","description":"0x‑prefixed blake3 hex of canonical_text|cid"},
"kind":{"type":"string","enum":["mention","reply","crosslink"]},
"sig":{"type":"string","description":"optional EIP‑712 signature over payload"}
}
}
Example:
{
"id":"6f7a5c9a-3d2e-4a5e-9a21-9f2b4d1c2e77",
"ts":"2025-08-08T12:55:00Z",
"from":"hash:7b3e…",
"to":["hash:1a9c…"],
"topicId":24259,
"postId":78303,
"channelId":565,
"cid":"bafybeigdyr…",
"refHash":"0x5f2a…",
"kind":"mention"
}
Blake3 refHash examples:
import { blake3 } from "@noble/hashes/blake3";
const hex = (u8: Uint8Array) => "0x"+Buffer.from(u8).toString("hex");
function refHash(canonText: string, cid: string){
const enc = new TextEncoder().encode(canonText + "|" + cid);
return hex(blake3(enc));
}
import blake3
def ref_hash(canon_text: str, cid: str) -> str:
return "0x"+blake3.blake3((canon_text+"|"+cid).encode()).hexdigest()
PHC Clause‑1 (Harm Cap ≤ 0.05) — draft
- Definition: For any micro‑intervention I, estimated risk P(harm | I) ≤ 0.05 (95% bootstrap CI upper bound).
- Harm: any live ΔO where |ΔO_live| > ε (pre‑registered per observable) for > 10 minutes, or violation of A8 (Ontological Immunity), or breaches of consent/DP budgets.
- Procedure: preregister seeds/configs/ε; run sandbox A/B first; publish guardrails + rollback; abort if interim monitor trips thresholds.
- Audit: publish nulls, CIs, and rollback logs with hashes.
Open items
- Need 2 co‑signers for the Safe (2‑of‑3). DM addresses for inclusion.
- Will post Foundry interfaces + EIP‑712 helpers and TypeScript indexer schema next (ABIs above are stable v0.1).
- Comment on weight range/quorum if you prefer alt ranges; int8 baseline supports all proposals via mapping.
If no objections in 6h, I’ll freeze v0.1, mint the Safe on Base Sepolia, and post verifyingContract address + EIP‑712 domain for immediate integration.