Specifica del protocollo
Stato: v1.1 — maggio 2026
Riferimenti: visione (il perché e il cosa)
Changelog rispetto alla v1.0: aggiunta la regola partyA != partyB (gli auto-scambi sono rifiutati) in §1.1 e §2.3. Dal 2026-06-12 la regola è deployata su Celo Sepolia all’indirizzo 0x889Cc9A46cCf77d44F4aA5fD501729d9c6916462 (rifiuta gli auto-scambi con SelfExchangeNotAllowed). Il pilota precedente (0xf32781ECd5252E50a760810dc4Ae65482BB5f696) è anteriore alla modifica e non implementa il check: resta on-chain come pilota tecnico ma non è più l’indirizzo di riferimento.
Premessa
Sezione intitolata “Premessa”Questo documento specifica il protocollo Compratempo: le regole con cui uno scambio di tempo fra due persone viene registrato in modo autorevole e permanente su una blockchain pubblica.
È il documento più formale della serie. Mentre la visione descrive il perché e l’architettura descrive come è fatta un’implementazione, questa specifica descrive lo standard — ciò che è fisso, pubblico, e su cui tutto il resto si appoggia. È anche la parte più difficile da cambiare: il protocollo vive in uno smart contract immutabile, quindi va specificato con cura e azzeccato al primo deploy.
Il nome del protocollo è Compratempo. “Time exchange protocol” è una glossa esplicativa in inglese, non un nome alternativo.
Cosa il protocollo è, e cosa non è
Sezione intitolata “Cosa il protocollo è, e cosa non è”Il protocollo Compratempo fa una sola cosa: registra che due persone si sono scambiate del tempo, in modo che il fatto sia pubblicamente verificabile, immutabile, e attribuito a entrambe. Da ogni registrazione nascono due tessere — oggetti digitali unici, uno per ciascun partecipante, che insieme compongono nel tempo il mosaico di una persona.
Il protocollo non si occupa di: come le persone si trovano, come negoziano, chi sono (identità), come si gestiscono le chiavi, come si paga il gas, come si trasmette un’eredità. Tutte queste cose vivono in strati superiori (l’implementazione compratempo-api) o sono questioni separate. Il protocollo conosce solo indirizzi blockchain, ore scambiate, e firme.
Questa minimalità è una scelta di principio: on-chain solo ciò che ha bisogno di autorevolezza pubblica e permanenza; tutto il resto fuori.
1. Il modello concettuale
Sezione intitolata “1. Il modello concettuale”1.1 Lo scambio
Sezione intitolata “1.1 Lo scambio”Uno scambio è un fatto compiuto fra due parti, A e B, in cui:
- A ha dato a B una certa quantità di ore (
hoursAToB) - B ha dato ad A una certa quantità di ore (
hoursBToA)
Una delle due quantità può essere zero: questo copre la donazione pura (A dà, B non ricambia) o la richiesta soddisfatta senza contropartita (B riceve, A non riceve nulla in cambio). Il protocollo non impone reciprocità né tassi di cambio: A e B hanno già deciso fra loro cosa è giusto, e il protocollo si limita a registrarlo.
Uno scambio è atomico e bilaterale: arriva al protocollo già concluso, accompagnato dal consenso firmato di entrambe le parti. Il protocollo non gestisce fasi intermedie (proposta, accettazione, esecuzione): quelle vivono nell’implementazione, off-chain. Al protocollo arriva solo il sigillo finale.
Uno scambio è anche interpersonale: A e B sono necessariamente due persone diverse (partyA != partyB). Il protocollo rifiuta gli auto-scambi. Le ragioni convergono da più direzioni:
- Concettuale. Lo scambio nel Compratempo è riconoscimento reciproco fra due. Una persona “che scambia con se stessa” non dona, non riceve, non viene riconosciuta — è un’autocelebrazione travestita da scambio, non ciò che il protocollo riconosce.
- Coerenza col tessuto sociale. Tutto il resto del Compratempo è costruito intorno alla fiducia che si propaga fra persone (connessioni, presentazioni, gruppi). L’auto-scambio è un caso degenere fuori da quel tessuto.
- Integrità dell’esperimento. L’auto-scambio permetterebbe di gonfiare artificialmente il proprio mosaico, inquinando i criteri di successo (durata, ritmo, crescita) di rumore senza senso.
- Strutturale (decisivo). Il protocollo emette due tessere gemelle per ogni scambio, con
tokenIdconsecutivi (vedi §1.2 e §3). Un auto-scambio rompe questa invariante: o si emettono due tessere allo stesso utente (sporcando la convenzione “una tessera per parte”), o se ne emette una sola e si distrugge la convenzione2N-1, 2N. Entrambi i casi sono “bombe matematiche” che inquinano le invarianti su cui poggia il resto del sistema.
1.2 Le tessere
Sezione intitolata “1.2 Le tessere”Ogni scambio registrato genera due tessere, una per ciascuna parte. Una tessera è un token non-fungibile (NFT, standard ERC-721) che rappresenta, dal punto di vista di chi la possiede, il ricordo di quello scambio.
Le due tessere di uno scambio sono gemelle: collegate fra loro (ognuna conosce l’identità dell’altra), condividono lo stesso scheletro oggettivo (le ore, le parti, il momento), ma possono avere metadati distinti — perché ogni partecipante ricorda lo scambio dal proprio lato, e può associarvi parole proprie. I metadati di ciascuna tessera sono separati e indipendenti, anche per ragioni di privacy (le note personali di una parte non sono necessariamente visibili all’altra).
Le tessere sono soulbound: legate per sempre al wallet che le possiede, non trasferibili. Una tessera nasce in un wallet e vi resta. Il protocollo non prevede alcun meccanismo di trasferimento — né vendita, né regalo, né eredità. (L’eredità, intesa come trasmissione del mosaico di una persona, è una questione di gestione dei wallet che vive fuori dal protocollo; vedi §5.)
1.3 Il mosaico
Sezione intitolata “1.3 Il mosaico”Il mosaico di una persona è l’insieme di tutte le tessere che possiede. Non è un concetto del protocollo (il protocollo conosce solo singole tessere e singoli wallet), ma emerge dalla lettura: dato un wallet, le sue tessere sono il suo mosaico. La composizione, la visualizzazione, l’aggregazione del mosaico avvengono negli strati superiori.
2. Il contratto
Sezione intitolata “2. Il contratto”Il protocollo è realizzato da un singolo smart contract, immutabile, deployato su Celo. Espone un’unica operazione di scrittura significativa e le funzioni di lettura standard.
2.1 Caratteristiche generali
Sezione intitolata “2.1 Caratteristiche generali”- Standard token: ERC-721 (ogni tessera è un NFT unico), con estensione ERC-5192 (soulbound / locked) per dichiarare pubblicamente la non-trasferibilità.
- Immutabile: nessun meccanismo di aggiornamento (no proxy). Il codice deployato è definitivo.
- Senza amministratore: nessun ruolo privilegiato, nessuna funzione di pausa, nessun owner con poteri. Il contratto è completamente autonomo. In caso di problemi gravi durante le fasi iniziali, la risposta è il deploy di un nuovo contratto, non la modifica dell’esistente.
2.2 L’operazione di registrazione
Sezione intitolata “2.2 L’operazione di registrazione”L’unica scrittura significativa è la registrazione di uno scambio. A livello concettuale (la firma esatta in Solidity sarà definita in implementazione):
recordExchange( partyA: address // wallet della parte A partyB: address // wallet della parte B hoursAToB: uint256 // ore che A dà a B (può essere 0) hoursBToA: uint256 // ore che B dà ad A (può essere 0) tokenURI_A: string // URI dei metadati della tessera di A tokenURI_B: string // URI dei metadati della tessera di B detailsHashA: bytes32 // hash dei metadati di A (integrità) detailsHashB: bytes32 // hash dei metadati di B (integrità) nonce: uint256 // anti-replay deadline: uint256 // scadenza di validità delle firme signatureA: bytes // firma EIP-712 della parte A signatureB: bytes // firma EIP-712 della parte B)Chiunque può inviare questa transazione (tipicamente l’implementazione compratempo-api tramite il proprio wallet operativo, che paga il gas). Ciò che conta non è chi invia, ma che le due firme siano valide: sono loro a garantire il consenso delle parti.
2.3 Cosa fa il contratto, in ordine
Sezione intitolata “2.3 Cosa fa il contratto, in ordine”- Verifica che
partyA != partyB(gli auto-scambi sono rifiutati; vedi §1.1). - Verifica che
deadlinenon sia trascorso. - Verifica che il
noncenon sia già stato usato (anti-replay). - Verifica
signatureAcontropartyA(firma EIP-712 valida del messaggio dello scambio). - Verifica
signatureBcontropartyB. - Assegna due nuovi
tokenIdsequenziali (es. N e N+1). - Emette la tessera di A, attribuendola a
partyA, con il suotokenURI_A. - Emette la tessera di B, attribuendola a
partyB, con il suotokenURI_B. - Registra il legame fra le due tessere gemelle.
- Marca entrambe le tessere come locked (soulbound, ERC-5192).
- Emette l’evento
ExchangeRecordedcon il resoconto completo.
Se una qualsiasi verifica fallisce (parti uguali, deadline, nonce, firme), la transazione viene respinta interamente: o lo scambio si registra del tutto, o non si registra affatto.
2.4 Il messaggio firmato (EIP-712)
Sezione intitolata “2.4 Il messaggio firmato (EIP-712)”Le parti firmano una struttura tipizzata secondo lo standard EIP-712, che permette ai wallet di mostrare in modo leggibile cosa si sta firmando.
Dominio: name: "Compratempo" version: "1" chainId: <id di Celo> verifyingContract: <indirizzo del contratto>
Messaggio (Exchange): partyA: address partyB: address hoursAToB: uint256 hoursBToA: uint256 detailsHashA: bytes32 detailsHashB: bytes32 nonce: uint256 deadline: uint256Entrambe le parti firmano lo stesso messaggio Exchange. Il contratto ricostruisce il messaggio dai parametri ricevuti e verifica che signatureA provenga da partyA e signatureB da partyB. La presenza di nonce e deadline impedisce che una firma venga riutilizzata o usata oltre il tempo previsto.
2.5 Storage e identificatori
Sezione intitolata “2.5 Storage e identificatori”Il contratto mantiene nello storage on-chain solo il minimo necessario:
- Per ogni
tokenId: il proprietario e iltokenURI(richiesti dallo standard ERC-721). - Il legame fra tessere gemelle.
- I
noncegià utilizzati (per l’anti-replay). - Un contatore per l’assegnazione sequenziale dei
tokenId.
Gli identificatori delle tessere sono sequenziali. Convenzione: per ogni scambio, la tessera di A riceve l’ID dispari, quella di B il successivo pari (o altra convenzione fissa equivalente), così che il legame gemello sia calcolabile senza accessi extra allo storage.
Tutto il resto — il resoconto completo dello scambio — vive nell’evento, non nello storage, per minimizzare i costi.
2.6 L’evento
Sezione intitolata “2.6 L’evento”ExchangeRecorded( exchangeId: uint256 (indexed) partyA: address (indexed) partyB: address (indexed) tokenIdA: uint256 tokenIdB: uint256 hoursAToB: uint256 hoursBToA: uint256 detailsHashA: bytes32 detailsHashB: bytes32 timestamp: uint256)Questo evento è la traccia permanente e pubblicamente leggibile dello scambio. L’observer dell’implementazione lo cattura e lo proietta nel proprio database per ricerche veloci; gli explorer blockchain lo mostrano; chiunque può verificarlo.
L’emissione delle due tessere produce inoltre i due eventi Transfer standard ERC-721 (dall’indirizzo zero ai wallet dei proprietari), e un evento Locked (ERC-5192) per ciascuna, a dichiarare la natura soulbound.
2.7 Funzioni di lettura
Sezione intitolata “2.7 Funzioni di lettura”Il contratto espone le funzioni di lettura standard ERC-721 (ownerOf, tokenURI, balanceOf, ecc.) più il minimo custom utile:
twinOf(tokenId)→ l’ID della tessera gemella.locked(tokenId)→ sempre vero (ERC-5192), a dichiarare la non-trasferibilità.
Tutte le query ricche — “tutte le tessere di un indirizzo”, “lo storico degli scambi”, le aggregazioni e le statistiche — non sono funzioni del contratto. Si ricostruiscono leggendo gli eventi, ed è compito dell’implementazione (l’observer + il database) renderle disponibili in modo efficiente. Il contratto è un registro autorevole, non un database queryabile.
2.8 La non-trasferibilità (soulbound)
Sezione intitolata “2.8 La non-trasferibilità (soulbound)”Le funzioni di trasferimento dello standard ERC-721 (transferFrom, safeTransferFrom, approve, setApprovalForAll) sono disabilitate: ogni chiamata viene respinta. Una tessera, una volta emessa, non può lasciare il wallet che la possiede. Questo è dichiarato pubblicamente tramite ERC-5192 (le tessere risultano “locked” a qualunque strumento conforme).
Non esiste alcuna eccezione nel protocollo: né regalo, né vendita, né eredità. La trasmissione del mosaico di una persona (per esempio in eredità) è una questione di gestione dei wallet, che vive fuori dal protocollo (§5).
3. I metadati delle tessere
Sezione intitolata “3. I metadati delle tessere”Il contratto memorizza, per ogni tessera, un tokenURI che punta a un documento di metadati ospitato su storage decentralizzato permanente (Arweave). Il contenuto del documento non è parte del protocollo in senso stretto, ma il protocollo ne garantisce l’integrità tramite il detailsHash firmato e registrato.
Struttura dei metadati (conforme alla convenzione ERC-721, con estensioni Compratempo):
{ "name": "<titolo leggibile, es. 'Scambio del 12 maggio 2026'>", "description": "<descrizione>", "image": "<URI dell'immagine generata della tessera>",
"compratempo": { "version": "1.0", "exchange_id": "<id dello scambio>", "twin_token_id": "<id della tessera gemella>", "my_role": "A" | "B", "i_gave": { "description": "<...>", "hours": <n> }, "i_received": { "description": "<...>", "hours": <n> }, "exchange_date": "<data>", "my_note": "<nota personale, eventualmente cifrata>" }}Lo scheletro oggettivo (ore, ruolo, data) è in chiaro. La nota personale (my_note) è privata di default: viene cifrata con la chiave pubblica del proprietario della tessera prima di essere scritta sullo storage pubblico, ed è leggibile solo da chi possiede la chiave corrispondente — salvo che il proprietario scelga esplicitamente di renderla condivisibile.
L’integrità è garantita: detailsHash (firmato dalle parti e registrato on-chain) è l’hash del documento di metadati. Se qualcuno modificasse il documento, l’hash non corrisponderebbe più e la manomissione sarebbe evidente.
4. Le garanzie del protocollo
Sezione intitolata “4. Le garanzie del protocollo”Il protocollo Compratempo offre queste garanzie, e nessun’altra:
- Autenticità del consenso. Uno scambio è registrato solo se entrambe le parti hanno firmato. Nessuno può registrare uno scambio falso a nome di altri.
- Immutabilità. Una volta registrato, uno scambio non può essere modificato né cancellato. Le tessere emesse restano per sempre.
- Attribuzione permanente. Ogni tessera è attribuita a un wallet preciso, e questa attribuzione non cambia mai (soulbound). Ciò che una persona ha fatto resta scolpito a suo nome.
- Verificabilità pubblica. Chiunque, in qualunque momento, può leggere lo storico degli scambi e verificarne l’integrità, senza bisogno di permessi e senza dipendere da alcuna autorità.
- Integrità dei dettagli. I metadati ricchi, pur vivendo fuori dalla chain, sono ancorati da un hash on-chain che ne impedisce la manomissione silenziosa.
5. Cosa è esplicitamente fuori dal protocollo
Sezione intitolata “5. Cosa è esplicitamente fuori dal protocollo”Per chiarezza, e per delimitare con precisione la responsabilità del protocollo, si elenca ciò che non gli appartiene:
- L’identità delle persone. Il protocollo conosce solo indirizzi blockchain. Il legame fra un indirizzo e una persona vive nell’implementazione.
- Il ciclo di vita di uno scambio prima del sigillo. Intenzioni, proposte, negoziazioni, accordi: tutto off-chain, nell’implementazione.
- La gestione delle chiavi e dei wallet. Custodia, creazione, sicurezza: responsabilità dell’implementazione.
- L’eredità e la trasmissione del mosaico. È una questione di gestione dei wallet (chi controlla un wallet), non di trasferimento di tessere (che sono soulbound e non si muovono). Vive fuori dal protocollo. In fase custodial si realizza come cessione di custodia gestita dall’implementazione; la modalità per la fase non-custodial è da definire a tempo debito, e comunque non toccherà il protocollo.
- Il pagamento del gas. Chi invia la transazione paga; il protocollo non se ne occupa. Nell’implementazione, paga il wallet operativo dell’istanza.
- Le ricerche, le aggregazioni, le statistiche, la composizione del mosaico. Si ricostruiscono dagli eventi, a cura dell’implementazione.
6. Note di implementazione
Sezione intitolata “6. Note di implementazione”Indicazioni per chi implementa, non vincolanti come lo standard ma utili a evitare errori noti.
- Libreria. Per costruire e inviare transazioni con pagamento del gas in valuta alternativa (USDC via fee abstraction di Celo), usare viem, che supporta il campo
feeCurrency. Verificare l’allowlist delle fee currency tramite il contrattoFeeCurrencyDirectorydi Celo, e usare l’indirizzo dell’adapter (non del token) per USDC, per via dei 6 decimali. - Firme. L’implementazione fa firmare alle parti il messaggio EIP-712 tramite i rispettivi wallet (custodial in fase pilota). Le firme sono operazioni off-chain, non costano gas.
- Storage dei metadati. Scrivere i metadati su Arweave prima di inviare la transazione, così che il
tokenURIsia già valido al momento dell’emissione. Conservare una copia locale per ricostruzione e per cache. - Anti-replay. L’implementazione genera un
nonceunivoco per ogni scambio e unadeadlineragionevole, e non riusa mai lo stesso nonce. - Conferme. L’observer considera uno scambio “registrato” solo dopo un numero sufficiente di blocchi di conferma, per robustezza rispetto a riorganizzazioni della catena.
7. Cosa resta da definire in implementazione
Sezione intitolata “7. Cosa resta da definire in implementazione”Questo documento fissa il protocollo. I seguenti dettagli si definiscono in fase di costruzione, restando entro i vincoli qui stabiliti:
- La firma Solidity esatta delle funzioni e i tipi precisi.
- Lo schema di cifratura della nota personale (libreria, gestione delle chiavi pubbliche).
- La generazione dell’immagine della tessera (linguaggio visivo, identità grafica derivata dai dati).
- I dettagli dell’integrazione con Arweave (formato dell’URI, gestione dei fallimenti di scrittura).
- La struttura precisa del documento di metadati oltre i campi qui indicati.
Specifica del protocollo Compratempo, v1.0 — maggio 2026. Lo standard è fisso e va azzeccato al primo deploy. I dettagli implementativi si definiscono in costruzione, entro questi vincoli.