Flussi di token, NFT e smart contract · Lezione 2 di 6
NFT e standard multi-token
9 min di lettura
I token non fungibili sono l’ambito in cui i dati on-chain vengono più spesso interpretati male dal pubblico. Un singolo trasferimento di NFT non dice nulla sul prezzo; una «vendita record» può essere un prestito rimborsato nella stessa transazione e le royalty dipendono dalle politiche del marketplace, non dal token. Un analista deve distinguere i semplici trasferimenti dalle vendite, decodificare gli eventi specifici del marketplace per ricavare il prezzo e la ripartizione delle commissioni e riconoscere i segnali del wash trading.
Eventi ERC-721
Un token ERC-721 (EIP-721) assegna a ogni ID token esattamente un proprietario. Lo standard definisce tre eventi:
| Evento | Topic | Dati |
|---|---|---|
Transfer(address indexed from, address indexed to, uint256 indexed tokenId) | topic0, from, to, tokenId | vuoti |
Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) | topic0, owner, approved, tokenId | vuoti |
ApprovalForAll(address indexed owner, address indexed operator, bool approved) | topic0, owner, operator | flag approved |
Poiché la firma canonica Transfer(address,address,uint256) è identica a quella di ERC-20, il topic0 è lo stesso (0xddf252ad…b3ef). La parola chiave indexed non fa parte della firma, quindi non modifica l’hash; cambia solo dove viene memorizzato il valore. Un Transfer ERC-721 ha quattro topic e dati vuoti; un Transfer ERC-20 ha tre topic e l’importo nei dati. Un decodificatore che si basa solo su topic0 interpreterà gli ID dei token come importi: è così che alcuni dashboard hanno segnalato «trasferimenti» di miliardi di unità di una collezione d’arte.
Il minting segue la convenzione ERC-20: from è l’indirizzo zero. ApprovalForAll è l’equivalente NFT di un’approvazione ERC-20 illimitata: consente a un operatore, di solito un contratto del marketplace, di trasferire ogni token che il proprietario possiede in quella collezione. Le campagne di phishing che ottengono una firma ApprovalForAll possono svuotare la collezione di un wallet con una sola transazione; quindi questo evento è la prima cosa da verificare quando una vittima segnala il furto di NFT.
Per confermare quale standard un contratto dichiara di implementare, chiama supportsInterface (ERC-165): l’ID dell’interfaccia ERC-721 è 0x80ac58cd, quello di ERC-1155 è 0xd9b67a26 e quello dello standard sulle royalty ERC-2981 è 0x2a55205a. Alcune collezioni iniziali precedono del tutto gli standard. CryptoPunks (2017) usa un proprio contratto con eventi personalizzati come PunkTransfer e PunkBought; le sue transazioni sono invisibili a un decodificatore che legge solo gli eventi Transfer di ERC-721.
Multi-token ERC-1155
ERC-1155 (EIP-1155) riunisce molti tipi di token in un unico contratto. Ogni tipo ha un id e ogni titolare possiede una quantità di quell’id, quindi lo stesso contratto può contenere una valuta fungibile di gioco (id 1, milioni di unità) e oggetti unici (quantità 1). Gli eventi di trasferimento sono:
TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value)TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values)
L’operator è l’account autorizzato a effettuare il trasferimento e dovrebbe essere il chiamante; pertanto, in una vendita sul marketplace, il contratto del marketplace compare come operator e il venditore come from. Come negli altri standard, il minting imposta from sull’indirizzo zero e il burning imposta to sull’indirizzo zero. I valori di topic0 sono 0xc3d58168…0f62 per TransferSingle e 0x4a39dc06…f7fb per TransferBatch.
Gli eventi batch contengono due array dinamici nei data, codificati con offset. Un batch che trasferisce tre unità dell’id 7 e un’unità dell’id 12 si decodifica così:
parola 0: 0x…40 offset dell’array ids (64 byte dall’inizio dei dati)
parola 1: 0x…a0 offset dell’array values (160 byte)
parola 2: 0x…02 lunghezza ids = 2
parola 3: 0x…07 ids[0] = 7
parola 4: 0x…0c ids[1] = 12
parola 5: 0x…02 lunghezza values = 2
parola 6: 0x…03 values[0] = 3
parola 7: 0x…01 values[1] = 1
Le prime due parole indicano dove inizia ciascun array; ogni array inizia poi con la propria lunghezza. Le coppie si leggono in base alla posizione: (id 7, 3 unità) e (id 12, 1 unità). In una tabella piatta, un evento TransferBatch diventa tante righe quanti sono gli id; dimenticare di espandere gli array fa sì che la maggior parte del volume dei contratti che usano molti batch venga omessa senza segnalarlo. ERC-1155 definisce anche ApprovalForAll e URI(string value, uint256 indexed id), che segnala modifiche ai metadati.
Vendite e semplici trasferimenti
Un evento Transfer da solo non contiene un prezzo. I proprietari trasferiscono NFT tra i propri wallet, li prestano, li distribuiscono tramite airdrop e li vendono con pagamenti effettuati off-chain. Una vendita si deduce da altre prove presenti nella stessa transazione: un flusso di pagamento (moneta nativa nelle tracce o un Transfer ERC-20, come WETH) e, idealmente, l’evento di regolamento specifico del marketplace.
Seaport, il protocollo open source usato da OpenSea e altri, emette OrderFulfilled con un’offerta (ciò che il creatore dell’ordine cede) e una consideration (ciò che il creatore e gli eventuali destinatari delle commissioni devono ricevere). Esempio semplificato decodificato di una vendita di un annuncio a 10 ETH:
{
"event": "OrderFulfilled",
"offerer": "0x5e11…a7b3",
"recipient": "0xb7e2…19cd",
"offer": [
{"itemType": 2, "token": "0xc011…77ab", "identifier": "4321", "amount": "1"}
],
"consideration": [
{"itemType": 0, "amount": "9450000000000000000", "recipient": "0x5e11…a7b3"},
{"itemType": 0, "amount": "50000000000000000", "recipient": "0xfee0…2c1d"},
{"itemType": 0, "amount": "500000000000000000", "recipient": "0xc4ea…b0b1"}
]
}
Il tipo di elemento 2 corrisponde a un token ERC-721 e il tipo 0 alla moneta nativa. L’offerer (il venditore) cede il token 4321; la consideration versa 9,45 ETH al venditore, 0,05 ETH (0,5%) a un indirizzo per le commissioni e 0,5 ETH (5%) al creatore. Il prezzo di vendita è la somma, 10 ETH. L’orientamento è importante: quando un venditore accetta un’offerta d’acquisto, l’offerer è l’acquirente, l’offerta è in WETH e l’NFT si trova nella consideration. Altre complicazioni:
- Lotti: un pagamento per più NFT; qualsiasi prezzo attribuito a ciascun articolo è una ripartizione e va indicato come tale.
- Aggregator: un router acquista da più marketplace in una transazione; attribuisci ciascun articolo all’ordine che è stato eseguito.
- Token di pagamento: il prezzo in WETH, stablecoin o altri token deve essere convertito usando il prezzo al blocco.
| Cosa si osserva nella transazione | Significato probabile |
|---|---|
| Solo Transfer dell’NFT | Spostamento tra wallet, regalo o vendita off-chain; nessun prezzo |
Transfer dell’NFT e pagamento all’indirizzo from | Probabile vendita; confermare con un evento del marketplace |
| Evento di regolamento del marketplace | Vendita con prezzo e ripartizione delle commissioni |
| Mint (da zero) con pagamento al contratto | Vendita primaria al prezzo di mint |
Royalty
ERC-2981 standardizza una chiamata, royaltyInfo(tokenId, salePrice), che restituisce un destinatario e un importo. È solo informativa: nulla nel token obbliga un marketplace a pagare. Alcune collezioni hanno provato a imporre il pagamento bloccando i trasferimenti sui marketplace che non pagavano, ma l’applicazione di questa regola si è indebolita. OpenSea, per esempio, ha disattivato il proprio strumento di applicazione on-chain e ha reso facoltative le commissioni per i creatori per le nuove collezioni dal 31 agosto 2023 e per le collezioni più vecchie che si erano affidate all’applicazione della regola dopo il 29 febbraio 2024. Per l’analisi, misura le royalty effettivamente pagate (gli elementi della consideration inviati al destinatario delle royalty) anziché l’aliquota dichiarata dal token e considera che l’aliquota effettiva può variare in base al marketplace e nel tempo.
Segnali di wash trading
Il wash trading consiste nel fare trading con sé stessi o con account che colludono per simulare volume, gonfiare un prezzo o ottenere ricompense. L’esempio più famoso è CryptoPunk 9998, il 28 ottobre 2021: una «vendita» di circa 124.457 ETH (all’epoca circa 532 milioni di dollari) in cui, come hanno spiegato i creatori della collezione, l’acquirente ha comprato il punk da sé stesso con denaro preso in prestito e ha rimborsato il prestito nella stessa transazione. Le ricompense legate al volume creano incentivi costanti: uno studio sottoposto a revisione paritaria sui mercati NFT di Ethereum (La Morgia et al., IEEE ICDCS 2023) ha rilevato che il wash trading rappresentava circa l’85% del volume su LooksRare, un marketplace che pagava ricompense in token proporzionali al volume di trading.
Tra i segnali usati da ricercatori e analisti figurano:
- Cicli chiusi: lo stesso token passa da A → B → A o circola in un piccolo gruppo di account.
- Finanziatore comune: acquirente e venditore sono stati finanziati dalla stessa fonte poco prima della transazione.
- Uscita comune: i proventi di entrambe le parti finiscono allo stesso indirizzo.
- Posizione a rischio zero: gli account che colludono terminano con lo stesso saldo complessivo, al netto delle commissioni.
- Autofinanziamento: prestiti flash o pagamenti nella stessa transazione che ritornano al pagatore.
- Prezzi ben al di sopra dell’intervallo recente della collezione e rapide transazioni ripetute dello stesso token.
Un semplice filtro per individuare le operazioni di andata e ritorno in una tabella nft_sales decodificata:
-- Token riacquistati dal venditore precedente entro 30 giorni
SELECT a.collection, a.token_id, a.seller, a.buyer,
a.price_eth AS first_price, b.price_eth AS return_price
FROM nft_sales a
JOIN nft_sales b
ON b.collection = a.collection
AND b.token_id = a.token_id
AND b.seller = a.buyer
AND b.buyer = a.seller
AND b.block_time > a.block_time
AND b.block_time <= a.block_time + INTERVAL '30' DAY
ORDER BY a.price_eth DESC;
La self-join abbina ogni vendita a una vendita successiva dello stesso token in cui i ruoli sono invertiti. La sintassi degli intervalli varia a seconda del motore. Un risultato è un indizio, non una conclusione: talvolta i collezionisti riacquistano davvero un’opera che avevano venduto. La fiducia aumenta quando convergono più segnali indipendenti, come un finanziatore comune, un’operazione di andata e ritorno e la riscossione di una ricompensa; per l’analisi dei finanziamenti, vedi la lezione Euristiche del modello account.
Focus sull'esame: Transfer, Approval e ApprovalForAll di ERC-721 e perché un Transfer ERC-721 ha quattro topic e dati vuoti; TransferSingle e TransferBatch di ERC-1155, il campo operator e l’espansione degli array batch; mint e burn tramite l’indirizzo zero; perché un trasferimento non ha un prezzo e come un evento del marketplace (offerta e consideration) fornisce il prezzo e la ripartizione delle commissioni; lotti e orientamento delle offerte d’acquisto; ERC-2981 come standard informativo e il passaggio a commissioni facoltative per i creatori; segnali di wash trading (cicli chiusi, finanziatore comune, uscita comune, posizione a rischio zero) e il caso CryptoPunk 9998.