Menggunakan Akun Smart Waves: Dari Lelang ke Program Bonus

gambar

Blockchain sering dikaitkan hanya dengan cryptocurrency, tetapi ruang lingkup teknologi DLT jauh lebih luas. Salah satu bidang yang paling menjanjikan untuk menggunakan blockchain adalah kontrak pintar yang berjalan secara otomatis dan tidak memerlukan kepercayaan di antara para pihak yang menyimpulkannya.

RIDE - bahasa untuk kontrak pintar

Waves telah mengembangkan bahasa khusus untuk kontrak pintar - RIDE. Dokumentasi lengkapnya ada di sini . Dan di sini - artikel tentang masalah ini tentang Habré.

Kontrak pada RIDE adalah predikat dan mengembalikan "benar" atau "salah" pada output. Karenanya, transaksi ditulis ke blockchain atau ditolak. Kontrak pintar sepenuhnya menjamin pemenuhan kondisi yang ditentukan. Pembuatan transaksi dari kontrak dalam RIDE saat ini tidak memungkinkan.

Saat ini, ada dua jenis kontrak pintar Waves: akun pintar dan aset pintar. Akun pintar adalah akun pengguna biasa, tetapi skrip dibuat untuk itu yang mengontrol semua transaksi. Skrip akun cerdas mungkin terlihat seperti ini:

match tx { case t: TransferTransaction | MassTransferTransaction => false case _ => true } 

tx adalah transaksi yang diproses yang kami izinkan menggunakan mekanisme pencocokan pola hanya jika itu bukan transaksi transfer. Pencocokan pola RIDE digunakan untuk memverifikasi jenis transaksi. Dalam skrip akun pintar, semua jenis transaksi yang ada dapat diproses.

Juga, variabel dapat dideklarasikan dalam skrip, konstruksi “jika-maka-lain” dan metode lain untuk pengecekan kondisi secara penuh dapat digunakan. Agar kontrak memiliki penyelesaian dan kompleksitas (biaya) yang terbukti, yang mudah diprediksi sebelum dimulainya kontrak, RIDE tidak mengandung loop dan operator seperti lompat.

Di antara fitur-fitur lain dari akun Waves adalah keberadaan "keadaan", yaitu keadaan akun. Jumlah pasangan tak terbatas (kunci, nilai) dapat ditulis ke status akun menggunakan transaksi data (DataTransaction). Selanjutnya, informasi ini dapat diproses baik melalui API REST, dan langsung dalam kontrak pintar.

Setiap transaksi dapat berisi berbagai bukti, di mana Anda dapat memasukkan tanda tangan peserta, ID transaksi yang diperlukan, dll.

Bekerja dengan RIDE melalui IDE memungkinkan Anda untuk melihat bentuk kontrak yang dikompilasi (jika dikompilasi), membuat akun baru dan mengatur skrip untuk itu, serta mengirim transaksi melalui baris perintah.

Untuk siklus penuh, termasuk membuat akun, memasang kontrak pintar dan mengirim transaksi, Anda juga dapat menggunakan perpustakaan untuk berinteraksi dengan REST API (misalnya, C #, C, Jawa, JavaScript, Python, Karat, Elixir). Untuk mulai bekerja dengan IDE, cukup klik tombol BARU.

Kemungkinan menggunakan kontrak pintar sangat luas: dari larangan transaksi ke alamat tertentu ("daftar hitam") hingga dApps kompleks.

Sekarang mari kita lihat contoh spesifik penggunaan kontrak pintar dalam bisnis: selama lelang, asuransi dan menciptakan program loyalitas.

Pelelangan

Salah satu syarat untuk pelelangan yang sukses adalah transparansi: penawar harus yakin bahwa tidak mungkin memanipulasi penawaran. Ini dapat dicapai berkat blockchain, di mana data yang tidak berubah pada semua taruhan dan waktu pembuatannya akan tersedia untuk semua peserta.

Di blockchain Waves, penawaran dapat direkam dalam status akun lelang melalui DataTransaction.

Anda juga dapat mengatur waktu mulai dan berakhirnya lelang menggunakan nomor blok: frekuensi pembuatan blok di blockchain Waves adalah sekitar 60 detik.

1. Pelelangan harga naik Inggris

Peserta dalam penawaran lelang bahasa Inggris, saling bersaing. Setiap taruhan baru harus melebihi yang sebelumnya. Pelelangan berakhir ketika tidak ada lagi keinginan untuk melebihi tawaran terakhir. Dalam hal ini, penawar tertinggi harus memberikan jumlah yang dinyatakan.

Ada juga opsi lelang di mana penjual menetapkan harga minimum untuk lot, dan harga akhir harus melebihi itu. Kalau tidak, lot tetap tidak terjual.

Dalam contoh ini, kami bekerja dengan akun yang dibuat khusus untuk pelelangan. Durasi lelang adalah 3000 blok, dan harga awal lot adalah 0,001 WAVES. Peserta dapat bertaruh dengan mengirimkan DataTransaction dengan kunci "harga" dan nilai penawarannya, dalam bukti transaksi, Anda perlu menambahkan kunci publik dan tanda tangan pengirim.

Harga taruhan baru harus lebih tinggi dari harga saat ini untuk kunci ini, dan peserta harus memiliki setidaknya token [new_state + komisi] dalam akun. Alamat bidder harus dimasukkan dalam bidang “pengirim” di DataTransaction, dan tinggi blok bid saat ini harus dalam periode lelang.

Jika pada akhir lelang, penawar telah menetapkan harga tertinggi, ia dapat mengirim ExchangeTransaction untuk membayar lot yang sesuai dengan harga dan pasangan mata uang yang ditunjukkan.

 let startHeight = 384120 let finishHeight = startHeight + 3000 let startPrice = 100000 #     let this = extract(tx.sender) let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' match tx { case d : DataTransaction => #,      let currentPrice = if isDefined(getInteger(this, "price")) #    then extract(getInteger(this, "price")) else startPrice #    let newPrice = extract(getInteger(d.data, "price")) #       let pk = d.proofs[1] let address = addressFromPublicKey(pk) let priceIsBigger = newPrice > currentPrice let fee = 700000 let hasMoney = wavesBalance(address) + fee >= newPrice let correctFields = size(d.data) == 2 && extract(getString(d.data, "sender")) == toBase58String(address.bytes) startHeight <= height && height <= finishHeight && priceIsBigger && hasMoney && correctFields && sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1]) case o : Order => #       let pk = o.proofs[1] let address = addressFromPublicKey(pk) let senderIsWinner = address == addressFromString(extract(getString(this, "sender"))) #,    ,    let correctAssetPair = o.assetPair.amountAsset == token && ! isDefined(o.assetPair.priceAsset) let correctAmount = o.amount == 1 let correctPrice = o.price == extract(getInteger(this, "price")) height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice && sigVerify(o.bodyBytes, o.proofs[0], o.proofs[1]) case _ => false } 

2. Pelelangan harga jatuh Belanda

Pada pelelangan Belanda, banyak yang awalnya ditawarkan dengan harga lebih tinggi dari apa yang bersedia dibayar pembeli. Harga dikurangi langkah demi langkah sampai salah satu peserta setuju untuk membeli lot pada harga saat ini.

Dalam contoh ini, kami menggunakan konstanta yang sama seperti pada yang sebelumnya, serta langkah harga saat menurunkan delta. Skrip akun memeriksa apakah peserta benar-benar yang pertama bertaruh. Dalam bukti transaksi, Anda perlu menambahkan kunci publik dan tanda tangan pengirim. Jika tidak, DataTransaction tidak diterima oleh blockchain.

 let startHeight = 384120 let finishHeight = startHeight + 3000 let startPrice = 100000000 let delta = 100 #     let this = extract(tx.sender) let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' match tx { case d : DataTransaction => let currentPrice = startPrice - delta * (height - startHeight) #   -  "price" let newPrice = extract(getInteger(d.data, "price")) #       let pk = d.proofs[1] let address = addressFromPublicKey(pk) let correctFields = extract(getString(d.data, "sender")) == toBase58String(address.bytes) && size(d.data) == 2 && newPrice == currentPrice #,         "sender" let noBetsBefore = !isDefined(getInteger(this, "sender")) let fee = 700000 let hasMoney = wavesBalance(address) - fee >= newPrice startHeight <= height && height <= finishHeight && noBetsBefore && hasMoney && correctFields && sigVerify(tx.bodyBytes, tx.proofs[0], tx.proofs[1]) case o : Order => #       let pk = o.proofs[1] let address = addressFromPublicKey(pk) #,           sender let senderIsWinner = address == addressFromString(extract(getString(this, "sender"))) #,  mount   ,   - - waves let correctAssetPair = o.assetPair.amountAsset == token && ! isDefined(o.assetPair.priceAsset) let correctAmount = o.amount == 1 let correctPrice = o.price == extract(getInteger(this, "price")) height > finishHeight && senderIsWinner && correctAssetPair && correctAmount && correctPrice && sigVerify(o.bodyBytes, o.proofs[0], o.proofs[1]) case _ => false } 

3. Lelang semua bayar

“All-pay” - lelang, semua peserta yang membayar penawaran, membayar, terlepas dari siapa yang memenangkan lot. Setiap peserta baru membayar taruhan, dan peserta yang telah membuat taruhan maksimum memenangkan lot.

Dalam contoh kami, setiap peserta lelang melakukan penawaran melalui DataTransaction dengan (kunci, nilai) * = ("pemenang", alamat), ("harga", harga). DataTransaction tersebut disetujui hanya jika untuk peserta ini sudah ada TransferTransaction dengan tanda tangannya dan nilainya lebih tinggi dari semua yang sebelumnya. Pelelangan berlanjut sampai mencapai ketinggian akhir.

 let startHeight = 1000 let endHeight = 2000 let token = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' match tx { case d: DataTransaction => #   -  "price" let newPrice = extract(getInteger(d.data, "price")) #       let pk = d.proofs[1] let address = addressFromPublicKey(pk) #        let proofTx = extract(transactionById(d.proofs[2])) height > startHeight && height < endHeight && size(d.data) == 2 #,   ,    ,   ,    && extract(getString(d.data, "winner")) == toBase58String(address.bytes) && newPrice > extract(getInteger(this, "price")) #,    && sigVerify(d.bodyBytes, d.proofs[0], d.proofs[1]) #  ,    && match proofTx { case tr : TransferTransaction => tr.sender == address && tr.amount == newPrice case _ => false } case t: TransferTransaction => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) || ( height > endHeight && extract(getString(this, "winner")) == toBase58String((addressFromRecipient(t.recipient)).bytes) && t.assetId == token && t.amount == 1 ) case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) } 

Asuransi / Crowdfunding

Pertimbangkan situasi di mana Anda perlu mengasuransikan aset pengguna dari kerugian finansial. Misalnya, pengguna ingin mendapatkan jaminan bahwa jika token terdepresiasi, ia akan dapat mengembalikan jumlah penuh yang dibayarkan untuk token ini dan siap membayar sejumlah asuransi yang wajar.

Untuk menerapkan ini, Anda perlu mengeluarkan "token asuransi." Lalu, skrip dipasang di akun pemegang polis yang memungkinkan Anda untuk hanya menjalankan transaksi ExchangeT yang memenuhi persyaratan tertentu.

Untuk mencegah pengeluaran ganda, Anda harus meminta pengguna untuk mengirim DataTransaction terlebih dahulu ke akun pemegang polis dengan (kunci, nilai) = (purchaseTransactionId, sellOrderId) dan melarang pengiriman DataTransactions dengan kunci yang sudah digunakan.

Oleh karena itu, bukti pengguna harus berisi ID transaksi pembelian token asuransi. Pasangan mata uang harus sama dengan dalam transaksi pembelian. Biaya juga harus sama dengan yang dicatat pada saat pembelian, dikurangi harga asuransi.

Dapat dipahami bahwa kemudian akun asuransi menebus token asuransi dari pengguna dengan harga yang tidak lebih rendah dari harga di mana dia membelinya: akun asuransi menciptakan ExchangeTransaction, pengguna menandatangani pesanan (jika transaksi diselesaikan dengan benar), akun asuransi menandatangani urutan kedua dan seluruh transaksi dan mengirimkannya ke blockchain .

Jika pembelian tidak terjadi, pengguna dapat membuat Pesanan sesuai dengan aturan yang dijelaskan dalam skrip dan mengirim transaksi ke blockchain. Sehingga pengguna dapat mengembalikan uang yang dihabiskan untuk pembelian token yang diasuransikan.

 let insuranceToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' #     let this = extract(tx.sender) let freezePeriod = 150000 let insurancePrice = 10000 match tx { #, ,   -,              case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key)) case o : Order => #     ,    if !isDefined(o.proofs[7]) then sigVerify(o.bodyBytes, o.proofs[0], o.senderPublicKey) else #     ,         let purchaseTx = transactionById(o.proofs[7]) let purchaseTxHeight = extract(transactionHeightById(o.proofs[7])) #    match purchaseTx { case purchase : ExchangeTransaction => let correctSender = purchase.sender == o.sender let correctAssetPair = o.assetPair.amountAsset == insuranceToken && purchase.sellOrder.assetPair.amountAsset == insuranceToken && o.assetPair.priceAsset == purchase.sellOrder.assetPair.priceAsset let correctPrice = o.price == purchase.price - insurancePrice && o.amount == purchase.amount let correctHeight = height > purchaseTxHeight + freezePeriod #,   -   ID   let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == o.id correctSender && correctAssetPair && correctPrice && correctHeight && correctProof case _ => false } case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) } 

Token asuransi dapat dijadikan aset cerdas, misalnya, untuk melarang transfernya ke pihak ketiga.

Skema ini juga dapat diterapkan untuk token crowdfunding, yang dikembalikan ke pemilik jika jumlah yang diperlukan belum dikumpulkan.

Pajak Transaksi

Kontrak pintar juga berlaku jika diperlukan untuk memungut pajak dari setiap transaksi dengan beberapa jenis aset. Ini dapat dilakukan melalui aset yang disponsori baru untuk transaksi dengan aset cerdas:

1. Kami merilis FeeCoin, yang akan dikirim ke pengguna dengan harga tetap: 0,01 WAVES = 0,001 FeeCoin.

2. Kami mengatur sponsor untuk FeeCoin dan nilai tukar: 0,001 WAVES = 0,001 FeeCoin.

3. Kami menetapkan skrip berikut untuk aset cerdas:

 let feeAssetId = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' let taxDivisor = 10 match tx { case t: TransferTransaction => t.feeAssetId == feeAssetId && t.fee == t.amount / taxDivisor case e: ExchangeTransaction| MassTransferTransaction => false case _ => true } 

Sekarang, setiap kali seseorang mentransfer aset pintar N, ia akan memberi Anda FeeCoin dalam jumlah N / taxDivisor (yang dapat dibeli dari Anda dengan 10 * N / taxDivisor WAVES), dan Anda akan memberikan N / taxDivisor WAVES. Akibatnya, laba (pajak) Anda akan menjadi 9 * N / taxDivisor WAVES.

Anda juga dapat mengenakan pajak menggunakan skrip aset cerdas dan Transaksi MassTransfer:

 let taxDivisor = 10 match tx { case t : MassTransferTransaction => let twoTransfers = size(t.transfers) == 2 let issuerIsRecipient = t.transfers[0].recipient == addressFromString("3MgkTXzD72BTfYpd9UW42wdqTVg8HqnXEfc") let taxesPaid = t.transfers[0].amount >= t.transfers[1].amount / taxDivisor twoTransfers && issuerIsRecipient && taxesPaid case _ => false } 

Program Cashback dan Loyalitas

Cashback adalah jenis program loyalitas di mana sebagian dari jumlah yang dihabiskan untuk suatu produk atau layanan dikembalikan kepada pembeli.

Saat menerapkan kasus ini menggunakan akun pintar, kita harus memeriksa bukti dengan cara yang sama seperti yang kita lakukan dalam kasus asuransi. Untuk mencegah pengeluaran ganda, sebelum menerima cashback, pengguna harus mengirim DataTransaction with (key, value) = (purchaseTransactionId, cashbackTransactionId).

Kita juga harus melarang kunci yang ada menggunakan DataTransaction. cashbackDivisor - unit yang dibagi dengan bagian cashback. Yaitu jika bagian cashback adalah 0,1, maka cashbackDivisor 1 / 0,1 = 10.

 let cashbackToken = base58'8jfD2JBLe23XtCCSQoTx5eAW5QCU6Mbxi3r78aNQLcNf' #     let this = extract(tx.sender) let cashbackDivisor = 10 match tx { #, ,   -,              case d : DataTransaction => size(d.data) == 1 && !isDefined(getBinary(this, d.data[0].key)) case e : TransferTransaction => #     ,    if !isDefined(e.proofs[7]) then sigVerify(e.bodyBytes, e.proofs[0], e.senderPublicKey) else #     ,         let purchaseTx = transactionById(e.proofs[7]) let purchaseTxHeight = extract(transactionHeightById(e.proofs[7])) #    match purchaseTx { case purchase : TransferTransaction => let correctSender = purchase.sender == e.sender let correctAsset = e.assetId == cashbackToken let correctPrice = e.amount == purchase.amount / cashbackDivisor #,   -   ID   let correctProof = extract(getBinary(this, toBase58String(purchase.id))) == e.id correctSender && correctAsset && correctPrice && correctProof case _ => false } case _ => sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) } 

Pertukaran atom

Pertukaran atom memungkinkan pengguna untuk bertukar aset tanpa bantuan pertukaran. Dalam pertukaran atom, kedua partisipan dalam transaksi diharuskan untuk mengkonfirmasinya dalam periode waktu tertentu.

Jika setidaknya salah satu peserta tidak memberikan konfirmasi transaksi yang benar dalam waktu yang ditentukan untuk transaksi, transaksi dibatalkan dan tidak ada pertukaran yang terjadi.

Dalam contoh kami, kami akan menggunakan skrip akun pintar berikut:

 let Bob = Address(base58'3NBVqYXrapgJP9atQccdBPAgJPwHDKkh6A8') let Alice = Address(base58'3PNX6XwMeEXaaP1rf5MCk8weYeF7z2vJZBg') let beforeHeight = 100000 let secret = base58'BN6RTYGWcwektQfSFzH8raYo9awaLgQ7pLyWLQY4S4F5' match tx { case t: TransferTransaction => let txToBob = t.recipient == Bob && sha256(t.proofs[0]) == secret && 20 + beforeHeight >= height let backToAliceAfterHeight = height >= 21 + beforeHeight && t.recipient == Alice txToBob || backToAliceAfterHeight case _ => false } 

Pada artikel berikutnya, kami akan mempertimbangkan penggunaan akun pintar dalam instrumen keuangan - seperti opsi, futures dan tagihan.

Source: https://habr.com/ru/post/id442238/


All Articles