Un Esempio di ICO Su Ergo

This page is machine-translated.
Alex Chepurnoy

10 aprile 2019

Questo articolo descrive un ICO (Offerta Iniziale di Monete) completo implementato in ErgoScript. L'esempio copre diverse caratteristiche importanti e innovative della Piattaforma Ergo e mostra come può supportare contratti complessi con una quantità minima di codice.

Parte 1. Preliminari

Una decisione di design importante in un protocollo di criptovaluta è specificare cosa spende effettivamente una transazione di spesa. Qui ci sono due possibilità. La prima è un modello basato su UTXO, come in Bitcoin, dove una transazione spende contenitori di asset usa e getta (chiamati 'monete' o UTXO in Bitcoin) e ne crea di nuovi. L'altra è un modello basato su account, come in Nxt, Ethereum o Waves, dove una transazione trasferisce una certa quantità di asset da un account esistente a lungo termine a un altro, possibilmente nuovo, account a lungo termine, con possibili effetti collaterali lungo il cammino, come l'esecuzione di contratti in Waves o Ethereum. A questo proposito, Ergo è simile a Bitcoin, perché utilizza l'approccio basato su UTXO, dove contenitori usa e getta chiamati box vengono spesi. È interessante notare che una transazione Ergo può anche avere input di dati che non vengono spesi, ma piuttosto utilizzati per fornire alcune informazioni dall'insieme attuale di box non spesi.

Non è banale creare un ICO su un modello basato su UTXO, perché, a differenza dei modelli basati su account, qui non c'è uno storage persistente esplicito. Tuttavia, Ergo porta una transazione di spesa nel contesto di esecuzione di uno script.
Con questo piccolo cambiamento diventa possibile esprimere dipendenze tra gli output e gli input delle transazioni. A sua volta, impostando le dipendenze possiamo eseguire anche programmi Turing-completi arbitrariamente complessi sopra la blockchain (vedi il "Self-reproducing Coins as Universal Turing Machine" paper). In questo articolo definiremo uno scenario concreto di un contratto multi-fase utilizzando un ICO, dove abbiamo tre fasi (finanziamento, emissione di token, prelievo).

Ora immagina un ICO per migliaia di partecipanti. A differenza di Ethereum, Ergo non fornisce la possibilità di memorizzare grandi set di dati e portarli avanti durante l'esecuzione del contratto. Piuttosto, consente di memorizzare solo circa 40 byte di intestazione di una struttura di dati, rappresentata come dizionario chiave -> valore, autenticata in modo simile a un albero di Merkle. Per accedere ad alcuni elementi nel dizionario, o per modificarlo, una transazione di spesa che attiva l'esecuzione dello script di protezione dovrebbe fornire prove di ricerca o modifica. Questo offre la possibilità a un contratto di autenticare potenzialmente enormi set di dati senza richiedere molta memoria per memorizzare lo stato del contratto. Tuttavia, memorizzare spazio nello stato (dei contratti attivi) significherebbe transazioni più grandi, ma questo problema è più facile dal punto di vista della scalabilità, e la scalabilità è una priorità assoluta per Ergo.

Parte 2. Il Contratto ICO

Ci potrebbero essere molti possibili scenari associati a un'Offerta Iniziale di Monete (ICO). In questo articolo consideriamo un ICO che vuole raccogliere almeno una certa quantità di fondi (in Ergs) per avviare il progetto. Una volta superata la soglia di finanziamento e terminato il periodo di finanziamento, il progetto viene avviato e i token ICO vengono emessi dal progetto in base al totale dei fondi raccolti. Nella fase di prelievo, che si estende all'infinito, gli investitori prelevano i token ICO in base all'importo che avevano investito durante il periodo di finanziamento. I passaggi del contratto sono brevemente descritti di seguito con dettagli forniti successivamente:

  • Prima, si svolge l'epoca di finanziamento. Inizia con una box del progetto che autentica un dizionario vuoto. Il dizionario è destinato a contenere coppie (investitore, saldo), dove l'investitore è uno script che protegge la box contenente i token prelevati. Per il saldo, assumiamo che 1 token sia uguale a 1 Ergo durante l'ICO. Durante l'epoca di finanziamento, è possibile solo inserire Ergs nella box del progetto.
    Una transazione di finanziamento spende la box del progetto e crea una nuova box del progetto con informazioni aggiornate. Per questo, una transazione di spesa per la box del progetto ha anche altri input che contengono script di prelievo degli investitori. Gli script degli investitori e i valori di input devono essere aggiunti all'albero della nuova box. Ci potrebbero essere molte transazioni di finanziamento concatenate.
  • In secondo luogo, il periodo di finanziamento termina, dopo di che l'albero che contiene i dati degli investitori diventa di sola lettura. Un albero autenticato potrebbe avere diverse operazioni di modifica consentite individualmente: inserimenti, cancellazioni, aggiornamenti, o tutte le operazioni potrebbero essere vietate (quindi l'albero potrebbe essere in modalità di sola lettura). Inoltre, questa transazione crea token del progetto ICO che saranno prelevati nella fase successiva. Il progetto può prelevare Ergs in questa fase.
  • In terzo luogo, gli investitori prelevano i loro token ICO. Per questo, una transazione di spesa crea output con condizioni di protezione e valori di token presi dall'albero. Le coppie prelevate vengono anche rimosse dall'albero. Ci potrebbero essere molte transazioni di spesa concatenate.

Queste tre fasi dovrebbero essere collegate insieme nell'ordine logico. Una sequenza di box viene utilizzata per raggiungere questi obiettivi.

Parte 3. I Dettagli del Contratto ICO

Ora è il momento di fornire dettagli e codice ErgoScript delle fasi del contratto ICO.

La Fase di Finanziamento

Nella fase di finanziamento, che viene per prima, assumiamo che inizialmente un progetto crea una box impegnandosi a un dizionario vuoto (memorizzato nel registro R5) con uno script di protezione descritto di seguito. Questa fase dura almeno fino all'altezza 2.000. Più concretamente, la prima transazione con un'altezza di 2.000 o superiore dovrebbe cambiare lo script della box di output come descritto nella sezione successiva (le transazioni a altezze inferiori devono produrre una box con lo stesso script).

La box del progetto controlla che sia sempre il primo input e output di una transazione. Gli altri input sono considerati input degli investitori. Un input dell'investitore contiene l'hash di uno script nel registro R4. Questo hash rappresenta lo script di prelievo che sarà utilizzato successivamente nella fase di prelievo. Gli hash così come i valori monetari di tutti gli input di investimento devono essere aggiunti al dizionario. La
transazione di spesa fornisce una prova che i dati degli investitori sono stati effettivamente aggiunti al dizionario, e la prova viene controllata nel contratto.

Non viene controllato nel sub-contratto di finanziamento che il dizionario consenta solo inserimenti, e non aggiornamenti di valori esistenti o rimozioni (non è difficile aggiungere un controllo esplicito però).

La transazione di spesa dovrebbe pagare una commissione, altrimenti, è improbabile che venga inclusa in un blocco. Pertanto, il contratto di finanziamento controlla che la transazione di spesa abbia due output (uno per se stessa, l'altro per pagare la commissione), la commissione non deve superare un certo limite (solo un nanoErg nel nostro esempio), e la proposizione di protezione dovrebbe essere tale che solo un miner possa spendere l'output (utilizziamo solo una variabile "feeProp" dall'ambiente di compilazione nel nostro esempio senza fornire ulteriori dettagli). Questo "feeProp" corrisponde a uno standard, anche se non richiesto dal protocollo.

Il codice qui sotto impone le condizioni descritte sopra. Si prega di notare che la
variabile ambientale "nextStageScriptHash" contiene l'hash dello script serializzato della fase di emissione.

    val selfIndexIsZero = INPUTS(0).id == SELF.id

    val proof = getVar[Coll[Byte]](1).get

    val inputsCount = INPUTS.size

    val toAdd: Coll[(Coll[Byte], Coll[Byte])] = INPUTS.slice(1, inputsCount).map({ (b: Box) =>
        val pk = b.R4[Coll[Byte]].get
        val value = longToByteArray(b.value)
        (pk, value)
    })

    val modifiedTree = SELF.R5[AvlTree].get.insert(toAdd, proof).get

    val expectedTree = OUTPUTS(0).R5[AvlTree].get

    val properTreeModification = modifiedTree == expectedTree

    val outputsCount = OUTPUTS.size == 2

    val selfOutputCorrect = if(HEIGHT < 2000) {
        OUTPUTS(0).propositionBytes == SELF.propositionBytes
    } else {
        blake2b256(OUTPUTS(0).propositionBytes) == nextStageScriptHash
    }

    val feeOutputCorrect = (OUTPUTS(1).value <= 1) && (OUTPUTS(1).propositionBytes == feeBytes)

    val outputsCorrect = outputsCount && feeOutputCorrect && selfOutputCorrect

    selfIndexIsZero && outputsCorrect && properTreeModification

La Fase di Emissione

Questa fase ha solo una transazione di spesa per passare alla fase successiva (la fase di prelievo). Le transazioni di spesa apportano le seguenti modifiche. In primo luogo, cambia l'elenco delle operazioni consentite sul dizionario da "solo inserimenti" a "solo rimozioni", poiché la fase successiva (prelievo) si occupa solo di rimuovere voci dal dizionario.

In secondo luogo, il contratto controlla che la giusta quantità di token ICO venga emessa. In Ergo, è consentito emettere un nuovo tipo di token per transazione, e l'identificatore del token dovrebbe essere uguale all'identificatore (unico) della prima box di input. Il sub-contratto di emissione controlla che un nuovo token sia stato emesso, e la sua quantità è uguale alla quantità di nanoErgs raccolti dall'ICO fino a quel momento.

In terzo luogo, il contratto controlla che una transazione di spesa stia effettivamente ricreando la box con lo script di protezione corrispondente alla fase successiva, la fase di prelievo.

Infine, il progetto dovrebbe prelevare gli Ergs raccolti, e ovviamente, ogni transazione di spesa dovrebbe pagare una commissione. Pertanto, il sub-contratto controlla che la transazione di spesa abbia effettivamente 3 output (uno ciascuno per la box dei token del progetto, la box di prelievo degli Ergs e la box della commissione), e che il primo output e output porti i token emessi. Poiché non specifichiamo i dettagli del prelievo di denaro del progetto, richiediamo una firma del progetto sulla transazione di spesa.

    val openTree = SELF.R5[AvlTree].get
    
    val closedTree = OUTPUTS(0).R5[AvlTree].get
    
    val digestPreserved = openTree.digest == closedTree.digest
    val keyLengthPreserved = openTree.keyLength == closedTree.keyLength
    val valueLengthPreserved = openTree.valueLengthOpt == closedTree.valueLengthOpt
    val treeIsClosed = closedTree.enabledOperations == 4
    
    val tokenId: Coll[Byte] = INPUTS(0).id
    
    val tokensIssued = OUTPUTS(0).tokens(0)._2
    
    val outputsCountCorrect = OUTPUTS.size == 3
    val secondOutputNoTokens = OUTPUTS(0).tokens.size == 1 && OUTPUTS(1).tokens.size == 0 && OUTPUTS(2).tokens.size == 0
    
    val correctTokensIssued = SELF.value == tokensIssued
    
    val correctTokenId = OUTPUTS(0).R4[Coll[Byte]].get == tokenId && OUTPUTS(0).tokens(0)._1 == tokenId
    
    val valuePreserved = outputsCountCorrect && secondOutputNoTokens && correctTokensIssued && correctTokenId
    val stateChanged = blake2b256(OUTPUTS(0).propositionBytes) == nextStageScriptHash
    
    val treeIsCorrect = digestPreserved && valueLengthPreserved && keyLengthPreserved && treeIsClosed
    
    projectPubKey && treeIsCorrect && valuePreserved && stateChanged

La Fase di Prelievo

In questa fase, agli investitori è consentito prelevare i token del progetto protetti da uno script di protezione predefinito (il cui hash è memorizzato nel dizionario). Supponiamo che il prelievo venga effettuato in lotti di dimensione N. Una transazione di prelievo, quindi, ha N + 2 output, dove il primo output porta il sub-contratto di prelievo e i token di saldo, l'ultimo output paga la commissione e i restanti N output hanno script di protezione e valori di token secondo il dizionario. Il contratto richiede due prove per gli elementi del dizionario: una che dimostra che i valori da prelevare sono effettivamente nel dizionario, e la seconda che dimostra che il dizionario risultante non ha i valori prelevati. Il sub-contratto è qui sotto.

    val removeProof = getVar[Coll[Byte]](2).get
    val lookupProof = getVar[Coll[Byte]](3).get
    val withdrawIndexes = getVar[Coll[Int]](4).get

    val out0 = OUTPUTS(0)

    val tokenId: Coll[Byte] = SELF.R4[Coll[Byte]].get

    val withdrawals = withdrawIndexes.map({(idx: Int) =>
        val b = OUTPUTS(idx)
        if(b.tokens(0)._1 == tokenId) {
            (blake2b256(b.propositionBytes), b.tokens(0)._2)
        } else {
            (blake2b256(b.propositionBytes), 0L)
        }
    })

    val withdrawValues = withdrawals.map({(t: (Coll[Byte], Long)) => t._2})

    val withdrawTotal = withdrawValues.fold(0L, { (l1: Long, l2: Long) => l1 + l2 })

    val toRemove = withdrawals.map({(t: (Coll[Byte], Long)) => t._1})

    val initialTree = SELF.R5[AvlTree].get

    val removedValues = initialTree.getMany(toRemove, lookupProof).map({(o: Option[Coll[Byte]]) => byteArrayToLong(o.get)})
    val valuesCorrect = removedValues == withdrawValues

    val modifiedTree = initialTree.remove(toRemove, removeProof).get

    val expectedTree = out0.R5[AvlTree].get

    val selfTokensCorrect = SELF.tokens(0)._1 == tokenId
    val selfOutTokensAmount = SELF.tokens(0)._2
    val soutTokensCorrect = out0.tokens(0)._1 == tokenId
    val soutTokensAmount = out0.tokens(0)._2

    val tokensPreserved = selfTokensCorrect && soutTokensCorrect && (soutTokensAmount + withdrawTotal == selfOutTokensAmount)

    val properTreeModification = modifiedTree == expectedTree

    val selfOutputCorrect = out0.propositionBytes == SELF.propositionBytes

    properTreeModification && valuesCorrect && selfOutputCorrect && tokensPreserved

Possibili Miglioramenti

Si prega di notare che ci sono molte sfumature che il nostro contratto di esempio ignora. Ad esempio, chiunque ascolti la blockchain è autorizzato a eseguire il contratto e costruire transazioni di spesa appropriate durante le fasi di finanziamento e prelievo. Nel mondo reale, potrebbe essere utilizzata un'ulteriore firma da parte del progetto o di un arbitro fidato.

Inoltre, non viene considerato alcun caso di autodistruzione nel contratto di prelievo, quindi vivrà fino a essere distrutto dai miner tramite il meccanismo di affitto di storage, potenzialmente per decenni o addirittura secoli. Per la fase di finanziamento, sarebbe ragionevole avere un input aggiuntivo dal progetto con un valore uguale a quello dell'output della commissione. E così via.

Share post

Ergo Infrastructure DAO: Decentralizzare la Spina Dorsale dell'Ecosistema Ergo

Ergo Infrastructure DAO: Decentralizzare la Spina Dorsale dell'Ecosistema Ergo

La missione di Ergo è sempre stata radicata nella decentralizzazione, non solo a livello di consenso, ma in tutto lo stack.

Ergo Platform

13 agosto 2025

Mew Finance: Un Toolkit DeFi Giocoso per l'Ecosistema Ergo

Mew Finance: Un Toolkit DeFi Giocoso per l'Ecosistema Ergo

Mew Finance è una suite di applicazioni decentralizzate sulla Blockchain Ergo.

Ergo Platform

12 agosto 2025

Lithos: Decentralizzare il Mining con Pool On-Chain

Lithos: Decentralizzare il Mining con Pool On-Chain

Lithos è un nuovo protocollo progettato per ristrutturare il funzionamento delle pool di mining spostandole on-chain, dando ai min.

Ergo Platform

24 luglio 2025

Sigma 6.0: Un Ergo più Intelligente e Flessibile

Sigma 6.0: Un Ergo più Intelligente e Flessibile

Sigma 6.0 è un importante aggiornamento proposto per la blockchain Ergo.

Ergo Platform

23 luglio 2025

Plasmare il Futuro di Rosen: Una Chiamata della Comunità su Cinque Proposte Chiave del Tesoro

Plasmare il Futuro di Rosen: Una Chiamata della Comunità su Cinque Proposte Chiave del Tesoro

Il co-fondatore di Rosen, Armeanio, ha presentato cinque nuove proposte al Tesoro di Rosen.

Ergo Platform

9 luglio 2025

L'Extended UTXO di Ergo e l'Ascesa dell'Intelligenza Economica Artificiale

L'Extended UTXO di Ergo e l'Ascesa dell'Intelligenza Economica Artificiale

Una Visione Pratica per Agenti Economici Autonomi Gli agenti economici autonomi sulla blockchain di Ergo svolgono un lavoro utile.

Ergo Platform

12 maggio 2025

ErgoHACK X: Intelligenza Artificiale sulla Blockchain di Ergo

ErgoHACK X: Intelligenza Artificiale sulla Blockchain di Ergo

Celebrare un Decennio di Innovazione Decentralizzata Unisciti al decimo anniversario di ErgoHACK e sii in prima linea nella rivolu.

Ergo Platform

10 aprile 2025

I partecipanti all'Hackaton V: mining and minting

I partecipanti all'Hackaton V: mining and minting

La registrazione per "ErgoHack V: Mining and Minting" è ufficialmente chiusa ed è tempo di esplorare ciò che i partecipanti hanno .

Ergo Platform

11 ottobre 2022

EIP37 Hardfork

EIP37 Hardfork

Dopo il merge di Ethereum, l'industria del mining di criptovalute ha assistito a un impressionante riorientamento del potere di ha.

Ergo Platform

3 ottobre 2022

ErgoHack V: incontra i nostri giudici

ErgoHack V: incontra i nostri giudici

Con le iscrizioni ora aperte, ErgoHack V si sta avvicinando rapidamente.

Ergo Platform

25 settembre 2022

Ergo: Dopo il merge di Ethereum

Ergo: Dopo il merge di Ethereum

Una discussione per la comunità mineraria Sono state un paio di settimane vorticose per l'industria del mining di criptovalute.

Ergo Platform

25 settembre 2022

La tabella di marcia di Ergo: cosa succederà. Parte 1

La tabella di marcia di Ergo: cosa succederà. Parte 1

Dal lancio sulla rete principale di Ergo il 1 luglio 2019, la blockchain ha raggiunto molti traguardi importanti.

Ergo Platform

24 settembre 2022

I premi di ErgoHack V

I premi di ErgoHack V

Con la fusione di Ethereum, stiamo assistendo a un cambiamento sismico nel panorama degli hashrate per le blockchain Proof of Work.

Ergo platform

18 settembre 2022

EIP-0028 di Ergo: ErgoAuth

EIP-0028 di Ergo: ErgoAuth

Quando si parla di blockchain, è importante ricordare che i wallet sono completamente anonimi.

Ergoplatform

4 settembre 2022

The Ergo Manifesto

The Ergo Manifesto

Il Manifesto Ergo desidera educare e offrire una panoramica di ciò che la tecnologia blockchain può raggiungere.

Ergo Foundation

3 settembre 2022

Ergo e il meccanismo di consenso di Autolykos: parte I

Ergo e il meccanismo di consenso di Autolykos: parte I

Quello che segue è un'analisi tecnica approfondita del meccanismo di consenso di Ergo, Autolykos.

Ergo Platform

28 agosto 2022

Ergo e il meccanismo di consenso di Autolykos: parte II

Ergo e il meccanismo di consenso di Autolykos: parte II

La scorsa settimana abbiamo introdotto un'analisi approfondita del meccanismo di consenso Autolykos di Ergo.

Ergo Platform

28 agosto 2022

Come acquistare Ergo da Kucoin

Come acquistare Ergo da Kucoin

Tutti gli aspetti di questo articolo non sono consigli finanziari. Ricontrolla tutte le informazioni fornite da altre fonti.

Ergoplatform

7 agosto 2022

Ethereum Mining Community e GPU Miners: il caso di Ergo dopo la fusione

Ethereum Mining Community e GPU Miners: il caso di Ergo dopo la fusione

Un cambiamento epocale in arrivo nel campo delle blockchain minabili Il panorama del mining di criptovalute Proof of Work sta per.

Ergoplatform

7 agosto 2022

Ergo: una risposta ai fallimenti della teoria monetaria moderna

Ergo: una risposta ai fallimenti della teoria monetaria moderna

Nel 2008, un gruppo o una persona sconosciuta ha rilasciato una riserva di valore peer-to-peer e l’ha chiamata Bitcoin.

Ergo platform

9 febbraio 2022

E' nata Ergoitaly.it

E' nata Ergoitaly.it

La prima community ufficiale Ergo in Italia Ergo è nato l'8 aprile 2019. Alle 20:41.

ErGonario

27 gennaio 2022