Ergo Üzerinde Bir ICO Örneği

This page is machine-translated.
Alex Chepurnoy

10 Nisan 2019

Bu makale, ErgoScript ile uygulanmış tam özellikli bir ICO'yu (Initial Coin Offering) tanımlamaktadır. Örnek, Ergo Platformu'nun birkaç önemli ve yenilikçi özelliğini kapsar ve karmaşık sözleşmeleri çok az kod ile nasıl destekleyebileceğini gösterir.

Bölüm 1. Ön Hazırlıklar

Bir kripto para protokolündeki önemli bir tasarım kararı, harcama işleminin aslında ne harcadığını belirtmektir. Burada iki olasılık vardır. Birincisi, Bitcoin'deki gibi UTXO tabanlı bir modeldir; burada bir işlem, bir kez kullanılan varlık konteynerlerini (Bitcoin'de 'coin' veya UTXO olarak adlandırılır) harcar ve yenilerini oluşturur. Diğeri, Nxt, Ethereum veya Waves'deki gibi hesap tabanlı bir modeldir; burada bir işlem, mevcut uzun ömürlü bir hesaptan başka, muhtemelen yeni, uzun ömürlü bir hesaba belirli bir miktar varlık aktarır ve bu süreçte, Waves veya Ethereum'daki sözleşme yürütme gibi yan etkiler olabilir. Bu açıdan Ergo, UTXO tabanlı yaklaşımı kullandığı için Bitcoin'e benzer; burada bir kez kullanılan konteynerler kutular olarak adlandırılır. İlginç bir şekilde, bir Ergo işlemi, harcanmayan ancak mevcut harcanmamış kutular setinden bazı bilgileri sağlamak için kullanılan veri girdi bileşenlerine de sahip olabilir.

UTXO tabanlı bir modelin üzerine bir ICO oluşturmak basit değildir, çünkü hesap tabanlı modellere kıyasla burada açık bir kalıcı depolama yoktur. Ancak, Ergo, bir harcama işlemini bir script'in yürütme bağlamına getirir.
Bu küçük değişiklikle, işlem çıktıları ve girdileri arasındaki bağımlılıkları ifade etmek mümkün hale gelir. Bağımlılıkları ayarlayarak, blok zincirinin üzerinde keyfi karmaşık Turing-tamamlayıcı programları bile çalıştırabiliriz (bkz. "Kendini Üreten Paralar Evrensel Turing Makinesi Olarak" makalesi). Bu makalede, bir ICO kullanarak çok aşamalı bir sözleşmenin somut bir senaryosunu tanımlayacağız; burada üç aşama (finansman, token ihraç etme, çekim) bulunmaktadır.

Şimdi binlerce katılımcı için bir ICO hayal edin. Ethereum'un aksine, Ergo büyük veri setlerini depolama ve bunları sözleşme yürütme süresince taşıma olanağı sağlamaz. Bunun yerine, Merkle ağacına benzer şekilde kimlik doğrulaması yapılmış anahtar -> değer sözlüğü olarak temsil edilen yaklaşık 40 baytlık bir veri yapısının başlığını depolamaya izin verir. Sözlükteki bazı öğelere erişmek veya bunları değiştirmek için, koruma script'inin yürütülmesini tetikleyen bir harcama işlemi, arama veya değiştirme kanıtları sağlamalıdır. Bu, bir sözleşmenin, sözleşme durumunu depolamak için çok fazla bellek gerektirmeden potansiyel olarak büyük veri setlerini kimlik doğrulamasına olanak tanır. Ancak, durumdaki depolama alanı (aktif sözleşmelerin) daha büyük işlemler anlamına gelecektir, ancak bu sorun ölçeklenebilirlik açısından daha kolaydır ve ölçeklenebilirlik Ergo için en yüksek önceliktir.

Bölüm 2. ICO Sözleşmesi

Bir İlk Para Arzı (ICO) ile ilişkili birçok olası senaryo olabilir. Bu makalede, projeyi başlatmak için en az belirli bir miktar fon (Erg cinsinden) toplamak isteyen bir ICO'yu ele alıyoruz. Fonlama eşiği aşıldığında ve fonlama süresi sona erdiğinde, proje başlatılır ve ICO token'ları, toplanan toplam fon miktarına dayanarak proje tarafından ihraç edilir. Çekim aşamasında, süresiz olarak uzanan, yatırımcılar, fonlama süresi boyunca yatırdıkları miktara dayanarak ICO token'larını çekerler. Sözleşme adımları aşağıda kısaca tanımlanmıştır ve detaylar daha sonra verilmiştir:

  • İlk olarak, finansman dönemi gerçekleşir. Bu, bir projenin kutusunun boş bir sözlüğü kimlik doğrulaması ile başlamasıyla başlar. Sözlük, (yatırımcı, bakiye) çiftlerini tutmak için tasarlanmıştır; burada yatırımcı, çekilen token'ları içeren kutuyu koruyan bir script'tir. Bakiye için, ICO sırasında 1 token'ın 1 Ergo'ya eşit olduğunu varsayıyoruz. Finansman dönemi boyunca, yalnızca Ergs, projenin kutusuna konulabilir.
    Bir finansman işlemi, projenin kutusunu harcar ve güncellenmiş bilgilerle yeni bir proje kutusu oluşturur. Bunun için, projenin kutusu için bir harcama işlemi, yatırımcıların çekim script'lerini tutan diğer girdilere de sahip olmalıdır. Yatırımcı script'leri ve girdi değerleri, yeni kutunun ağacına eklenmelidir. Birçok zincirleme finansman işlemi olabilir.
  • İkinci olarak, finansman dönemi sona erer; ardından yatırımcı verilerini tutan ağaç yalnızca okunabilir hale gelir. Kimlik doğrulaması yapılmış bir ağaç, bireysel olarak farklı değiştirme işlemlerine izin verebilir: eklemeler, silmeler, güncellemeler veya tüm işlemler yasaklanabilir (bu nedenle ağaç yalnızca okunabilir modda olabilir). Ayrıca, bu işlem, bir sonraki aşamada çekilecek ICO projesinin token'larını oluşturur. Proje, bu aşamada Ergs çekebilir.
  • Üçüncü olarak, yatırımcılar ICO token'larını çekerler. Bunun için, bir harcama işlemi, koruma koşulları ve ağaçtan alınan token değerleri ile çıktılar oluşturur. Çekilen çiftler de ağaçtan temizlenir. Birçok zincirleme harcama işlemi olabilir.

Bu üç aşama, mantıksal sırayla birbirine bağlanmalıdır. Bu hedeflere ulaşmak için bir dizi kutu kullanılır.

Bölüm 3. ICO Sözleşmesi Detayları

Artık ICO sözleşmesi aşamalarının detaylarını ve ErgoScript kodunu sağlama zamanı.

Finansman Aşaması

Finansman aşamasında, ilk olarak bir projenin, aşağıda tanımlanan bazı koruma script'i ile boş bir sözlüğe (R5 kaydında depolanan) taahhüt eden bir kutu oluşturduğunu varsayıyoruz. Bu aşama en az 2,000 yüksekliğine kadar sürer. Daha somut olarak, 2,000 veya daha fazla yüksekliğe sahip ilk işlem, çıktı kutusunun script'ini bir sonraki bölümde açıklandığı gibi değiştirmelidir (daha düşük yüksekliklerdeki işlemler, aynı script ile bir kutu çıkarmalıdır).

Projenin kutusu, her zaman bir işlemin ilk girişi ve çıktısı olduğunu kontrol eder. Diğer girdiler, yatırımcıların girdileri olarak kabul edilir. Bir yatırımcının girişi, R4 kaydındaki bir script'in hash'ini içerir. Bu hash, çekim aşamasında daha sonra kullanılacak olan çekim script'ini temsil eder. Hash'ler ve tüm yatırımcı girdilerinin parasal değerleri sözlüğe eklenmelidir.
Harcama işlemi, yatırımcı verilerinin gerçekten sözlüğe eklendiğine dair bir kanıt sağlar ve bu kanıt sözleşmede kontrol edilir.

Finansman alt sözleşmesinde, sözlüğün yalnızca eklemelere izin verdiği ve mevcut değerlerin güncellenmesine veya kaldırılmasına izin vermediği kontrol edilmez (ancak açık bir kontrol eklemek zor değildir).

Harcama işlemi bir ücret ödemelidir; aksi takdirde, bir blokta yer alması pek olası değildir. Bu nedenle, finansman sözleşmesi, harcama işleminin iki çıktısı olduğunu kontrol eder (biri kendisi için, diğeri ücreti ödemek için), ücretin belirli bir sınırdan (örneğin, örneğimizde yalnızca bir nanoErg) fazla olmaması gerektiğini ve koruma önerisinin yalnızca bir madencinin çıktıyı harcayabileceği şekilde olması gerektiğini kontrol eder (örneğimizde herhangi bir detay vermeden yalnızca "feeProp" adlı bir değişken kullanıyoruz). Bu "feeProp", standart bir durumu temsil eder, ancak protokol tarafından zorunlu değildir.

Aşağıdaki kod, yukarıda tanımlanan koşulları zorunlu kılar. Lütfen "nextStageScriptHash" ortam değişkeninin, ihraç aşamasının serileştirilmiş script'inin hash'ini içerdiğini unutmayın.

    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

İhraç Aşaması

Bu aşamanın, bir sonraki aşamaya (çekim aşaması) geçmek için yalnızca bir harcama işlemi vardır. Harcama işlemi, sözlük üzerindeki izin verilen işlemler listesini "sadece eklemeler" yerine "sadece kaldırmalar" olarak değiştirir; çünkü bir sonraki aşama (çekim), yalnızca sözlükten girişleri kaldırmakla ilgilidir.

İkincisi, sözleşme, doğru miktarda ICO token'ının ihraç edildiğini kontrol eder. Ergo'da, her işlem başına bir yeni tür token ihraç edilmesine izin verilir ve token'ın tanımlayıcısı, ilk girdi kutusunun (benzersiz) tanımlayıcısına eşit olmalıdır. İhraç alt sözleşmesi, yeni bir token'ın ihraç edildiğini ve miktarının ICO tarafından şimdiye kadar toplanan nanoErg miktarına eşit olduğunu kontrol eder.

Üçüncüsü, sözleşme, bir harcama işleminin gerçekten bir sonraki aşamaya, çekim aşamasına karşılık gelen koruma script'i ile kutuyu yeniden oluşturduğunu kontrol eder.

Son olarak, proje toplanan Ergs'i çekmelidir ve elbette, her harcama işlemi bir ücret ödemelidir. Bu nedenle, alt sözleşme, harcama işleminin gerçekten 3 çıktısı olduğunu (biri proje token'ları kutusu, biri Erg çekim kutusu ve biri ücret kutusu için) ve ilk çıktı ve çıktının ihraç edilen token'ları taşıdığını kontrol eder. Proje para çekim detaylarını belirtmediğimiz için, harcama işlemi üzerinde bir proje imzası gerektiriyoruz.

    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

Çekim Aşaması

Bu aşamada, yatırımcıların, sözlükte saklanan önceden tanımlanmış bir koruma script'i ile korunan proje token'larını çekmelerine izin verilir. Diyelim ki çekim, N boyutunda gruplar halinde yapılmaktadır. Bu nedenle, bir çekim işlemi, N + 2 çıktıya sahiptir; burada ilk çıktı, çekim alt sözleşmesini ve bakiye token'larını taşırken, son çıktı ücreti öder ve kalan N çıktı, sözlüğe göre koruma script'leri ve token değerlerine sahiptir. Sözleşme, sözlük öğeleri için iki kanıt gerektirir: biri, çekilecek değerlerin gerçekten sözlükte olduğunu kanıtlayan, diğeri ise sonuçta oluşan sözlüğün çekilen değerleri içermediğini kanıtlayan. Aşağıda alt sözleşme bulunmaktadır.

    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

Olası Geliştirmeler

Lütfen, örnek sözleşmemizin birçok nüansı göz ardı ettiğini unutmayın. Örneğin, blok zincirini dinleyen herkes, finansman ve çekim aşamaları sırasında sözleşmeyi yürütme ve uygun harcama işlemleri oluşturma hakkına sahiptir. Gerçek dünyada, projeden veya güvenilir bir hakemden ek bir imza kullanılabilir.

Ayrıca, çekim sözleşmesinde kendini yok etme durumu dikkate alınmamıştır, bu nedenle, depolama kirası mekanizması aracılığıyla madenciler tarafından yok edilene kadar, potansiyel olarak on yıllar veya hatta yüzyıllar boyunca yaşayacaktır. Finansman aşaması için, proje tarafından, ücret çıktısının değerine eşit bir ek girdi olması makul olacaktır. Ve daha fazlası.

Share post

Ergo Altyapı DAO: Ergo Ekosisteminin Omurgasını Merkeziyetsizleştirmek

Ergo Altyapı DAO: Ergo Ekosisteminin Omurgasını Merkeziyetsizleştirmek

Ergo’nun misyonu her zaman merkeziyetsizlikte kök salmıştır, sadece konsensüs katmanında değil, tüm yığın boyunca.

Ergo Platform

13 Ağustos 2025

Mew Finance: Ergo Ekosistemi için Eğlenceli Bir DeFi Araç Seti

Mew Finance: Ergo Ekosistemi için Eğlenceli Bir DeFi Araç Seti

Mew Finance, Ergo Blockchain üzerinde merkeziyetsiz bir uygulama setidir.

Ergo Platform

12 Ağustos 2025

Lithos: Madenciliği On-Chain Havuzlarla Merkeziyetsizleştirmek

Lithos: Madenciliği On-Chain Havuzlarla Merkeziyetsizleştirmek

Lithos, madencilik havuzlarının nasıl çalıştığını köklü bir şekilde değiştirmek için tasarlanmış yeni bir protokoldür; havuzları o.

Ergo Platform

24 Temmuz 2025

Sigma 6.0: Daha Akıllı, Daha Esnek Ergo

Sigma 6.0: Daha Akıllı, Daha Esnek Ergo

Sigma 6.0 Ergo blockchain için önerilen büyük bir güncellemedir.

Ergo Platform

23 Temmuz 2025

Rosen'ın Geleceğini Şekillendirmek: Beş Ana Hazine Teklifi Üzerine Topluluk Çağrısı

Rosen'ın Geleceğini Şekillendirmek: Beş Ana Hazine Teklifi Üzerine Topluluk Çağrısı

Rosen kurucu ortağı Armeanio, Rosen Hazine'sine beş yeni teklif sunmuştur.

Ergo Platform

9 Temmuz 2025

Ergo'nun Genişletilmiş UTXO'su ve Yapay Ekonomik Zekanın Yükselişi

Ergo'nun Genişletilmiş UTXO'su ve Yapay Ekonomik Zekanın Yükselişi

Otonom Ekonomik Ajanlar için Pratik Bir Vizyon Otonom ekonomik ajanlar, Ergo blok zincirinde gerçek bir dijital ekonomide faydalı.

Ergo Platform

12 Mayıs 2025

ErgoHACK X: Ergo Blok Zincirinde Yapay Zeka

ErgoHACK X: Ergo Blok Zincirinde Yapay Zeka

Dağıtık İnovasyonun Onuncu Yılı yıl dönümü ErgoHACK'e katılın ve Ergo blok zincirindeki AI devriminin ön saflarında yer alın! Yara.

Ergo Platform

10 Nisan 2025