
Pada artikel ini, kita akan melihat dua contoh bagaimana menulis kontrak pintar dalam C ++ menggunakan
WASM berdasarkan jaringan blockchain Ontology. Hari ini, setelah beberapa bulan operasi yang stabil dalam mode uji,
Ontology meluncurkan WASM di jaringan utama, yang memungkinkan tanpa rasa sakit dan dengan biaya lebih rendah untuk mentransfer kontrak dApp dengan logika bisnis yang rumit ke blockchain, sehingga secara signifikan memperkaya ekosistem dApp.
Ontologi Wasm juga mendukung pembuatan kontrak pintar dalam bahasa Rust, Anda dapat membacanya di
sini .
Di bawah ini adalah dua contoh dari kontrak pintar: pertama, tulis "Halo dunia!" dan kemudian membuat amplop uang virtual yang dapat dikirim ke teman sebagai hadiah.
Pengembangan kontrak WASM menggunakan C ++
Contoh 1. Hello World
Mari kita mulai dengan Hello World:
#include<ontiolib/ontio.hpp> #include<stdio.h> using namespace ontio; class hello:public contract { public: using contract::contract: void sayHello(){ printf("hello world!"); } }; ONTIO_DISPATCH(hello, (sayHello));
Pembuatan kontrak
Kompiler Ontology Wasm CDT berisi titik masuk dan parameter parsing, sehingga pengembang tidak perlu mendefinisikan ulang metode input. Selanjutnya, untuk menulis logika layanan, Anda dapat memanggil metode API dari kontrak pintar.
ONTIO_DISPATCH(hello, (sayHello));
Dalam contoh di atas, kami hanya mendukung sayHello sejauh ini:
printf("hello world!");
"Halo Dunia!" akan ditampilkan di log simpul debug. Saat menulis kontrak pintar secara langsung, printf hanya dapat digunakan untuk debugging, karena kontrak pintar itu sendiri berisi perintah yang lebih fungsional.
API kontrak pintar
Ontology Wasm menyediakan API berikut untuk berinteraksi dengan blockchain server:

Contoh 2: Amplop Uang
Sekarang mari kita lihat contoh yang lebih kompleks menggunakan API kontrak pintar Wasm.
Dalam contoh ini, kami akan menulis amplop uang virtual, analog dari amplop merah (hongbao) adalah fitur populer dari pembawa pesan Wechat Cina, yang memungkinkan Anda mengirim uang ke teman dalam obrolan. Pengguna menerima pesan dalam bentuk amplop merah, membukanya dan uang secara otomatis dikreditkan ke saldo akun.
Sebagai bagian dari kontrak pintar, pengguna dapat menggunakan kontrak ini untuk mengirim token ONT, ONG, atau OEP-4 menggunakan amplop uang virtual kepada teman-teman mereka, yang kemudian dapat mentransfer token ke dompet blockchain mereka.
Bersiap untuk membuat kontrak
Pertama, buat file kontrak sumber dan beri nama redEnvelope.cpp. Selanjutnya, kami membutuhkan tiga API untuk kontrak ini:
- createRedEnvelope : Buat amplop uang
- queryEnvelope : Minta informasi amplop
- claimEnvelope : buka amplop dan terima uang
#include<ontiolib/ontio.hpp> using namespace ontio; class redEnvlope: public contract{ } ONTIO_DISPATCH(redEnvlope, (createRedEnvlope)(queryEnvlope)(claimEnvelope));
Sekarang kita perlu menyimpan nilai kunci. Dalam kontrak pintar, data disimpan dalam konteks kontrak sebagai nilai-kunci, dan kami perlu menambahkan awalan ke data KUNCI untuk permintaan berikutnya.
Di bawah ini kami menetapkan tiga awalan yang akan kami gunakan:
std::string rePrefix = "RE_PREFIX_"; std::string sentPrefix = "SENT_COUNT_"; std::string claimPrefix = "CLAIM_PREFIX_";
Karena kontrak mendukung token ontologi - ONT dan ONG, kami dapat menentukan alamat kontrak mereka terlebih dahulu. Tidak seperti kontrak pintar standar, alamat kontrak Ontology sendiri adalah tetap dan tidak berasal dari hash kontrak.
address ONTAddress = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}; address ONGAddress = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2};
Selanjutnya, Anda perlu menyimpan informasi tentang token yang digunakan dalam kontrak: alamat token kontrak, jumlah total amplop dan jumlah amplop.
struct receiveRecord{ address account;
Berikut ini adalah operasi makro yang didefinisikan oleh Ontology Wasm CDT, yang digunakan untuk serialisasi sebelum penataan data.
ONTLIB_SERIALIZE(receiveRecord,(account)(amount))
Membuat Amplop
Sekarang kami telah menyelesaikan persiapan yang diperlukan, kami akan memulai pengembangan logika API.
1. Saat membuat amplop uang, perlu untuk menunjukkan alamat pemilik, jumlah dan jumlah amplop, serta alamat token:
bool createRedEnvlope(address owner,asset packcount, asset amount,address tokenAddr ){ return true; }
2. Periksa tanda tangan pemilik, jika tidak kami akan mengembalikan (mengembalikan transaksi) dan keluar:
ontio_assert(check_witness(owner),"checkwitness failed");
Catatan : ontio_assert (expr, errormsg): false expr mengembalikan kesalahan dan keluar dari kontrak.
3. Jika token ONT digunakan dalam amplop, penting untuk diingat bahwa, ONT tidak terfragmentasi (setidaknya 1 ONT). Maka jumlah total amplop uang harus lebih besar dari atau sama dengan jumlah token untuk memastikan bahwa setidaknya ada 1 ONT di setiap amplop:
if (isONTToken(tokenAddr)){ ontio_assert(amount >= packcount,"ont amount should greater than packcount"); }
4. Selanjutnya, kami menentukan bagi pemegang amplop jumlah total amplop uang yang ia kirim:
key sentkey = make_key(sentPrefix,owner.tohexstring()); asset sentcount = 0; storage_get(sentkey,sentcount); sentcount += 1; storage_put(sentkey,sentcount);
5. Hasilkan hash dari amplop - pengidentifikasi yang menandai amplop ini:
H256 hash ; hash256(make_key(owner,sentcount),hash) ; key rekey = make_key(rePrefix,hash256ToHexstring(hash));
6. Kami akan menerjemahkan token ke dalam kontrak. Kami mengetahui alamat kontrak yang saat ini sedang dieksekusi menggunakan perintah self_address (), maka kami akan mentransfer jumlah token yang ditetapkan ke kontrak berdasarkan jenis token:
address selfaddr = self_address(); if (isONTToken(tokenAddr)){ bool result = ont::transfer(owner,selfaddr ,amount); ontio_assert(result,"transfer native token failed!"); }else if (isONGToken(tokenAddr)){ bool result = ong::transfer(owner,selfaddr ,amount); ontio_assert(result,"transfer native token failed!"); }else{ std::vector<char> params = pack(std::string("transfer"),owner,selfaddr,amount); bool res; call_contract(tokenAddr,params, res ); ontio_assert(res,"transfer oep4 token failed!"); }
Catatan 1: untuk ONT dan ONG, Ontology Wasm CDT menyediakan API ont :: transfer untuk mentransfer token; Token OEP-4 harus dikirim menggunakan metode panggilan lintas kontrak konvensional.
Catatan 2: seperti alamat dompet biasa, alamat kontrak dapat menerima semua jenis token. Namun, alamat kontrak dihasilkan oleh hash biner yang dikompilasi dan dengan demikian tidak memiliki kunci pribadi yang sesuai dan tidak dapat menggunakan token kontrak. Jika Anda belum menyiapkan kunci pribadi, maka Anda tidak akan dapat mengelola token ini.
7. Simpan informasi tentang kontrak di gudang data:
struct envlopeStruct es ; es.tokenAddress = tokenAddr; es.totalAmount = amount; es.totalPackageCount = packcount; es.remainAmount = amount; es.remainPackageCount = packcount; es.records = {}; storage_put(rekey, es);
8. Kirim pemberitahuan tentang pembuatan amplop. Ini adalah proses asinkron untuk menjalankan kontrak yang cerdas, kontrak juga akan mengirim pemberitahuan hasil eksekusi. Format eksekusi dapat ditentukan oleh penulis kontrak.
char buffer [100]; sprintf(buffer, "{\"states\":[\"%s\", \"%s\", \"%s\"]}","createEnvlope",owner.tohexstring().c_str(),hash256ToHexstring(hash).c_str()); notify(buffer); return true;
Hore, amplop uang hampir siap. Sekarang mari kita lihat bagaimana cara meminta informasi amplop.
Amplop Permintaan (Query
Logika permintaan cukup sederhana, Anda hanya perlu mendapatkan informasi dan format dari penyimpanan data, dan kemudian output:
std::string queryEnvlope(std::string hash){ key rekey = make_key(rePrefix,hash); struct envlopeStruct es; storage_get(rekey,es); return formatEnvlope(es); }
Catatan: untuk operasi kontrak pintar hanya baca (mis. Kueri), Anda dapat memeriksa hasilnya melalui pra-eksekutif. Tidak seperti panggilan kontrak reguler, pra-eksekutif tidak memerlukan tanda tangan dompet dan karenanya tidak memerlukan komisi dalam ONG. Setelah melakukan ini, pengguna lain sekarang dapat mengajukan amplop jika mereka memiliki hash amplop (ID amplop).
Menerima Amplop
Pada tahap ini, kami telah berhasil mentransfer token ke kontrak pintar, sekarang, sehingga teman-teman Anda dapat mengklaim bagian dalam amplop dengan sukses, Anda harus mengirim mereka pengenal amplop (hash).
1. Untuk menerima amplop, Anda harus memasukkan alamat akun dan hash amplop:
bool claimEnvlope(address account, std::string hash){ return true; }
2. Selanjutnya, kontrak akan memverifikasi tanda tangan akun Anda untuk memastikan bahwa Anda adalah pemiliknya. Setiap akun hanya dapat mengajukan satu amplop:
ontio_assert(check_witness(account),"checkwitness failed"); key claimkey = make_key(claimPrefix,hash,account); asset claimed = 0 ; storage_get(claimkey,claimed); ontio_assert(claimed == 0,"you have claimed this envlope!");
3. Periksa apakah amplop diterima sesuai dengan informasi hash yang diterima dari toko:
key rekey = make_key(rePrefix,hash); struct envlopeStruct es; storage_get(rekey,es); ontio_assert(es.remainAmount > 0, "the envlope has been claimed over!"); ontio_assert(es.remainPackageCount > 0, "the envlope has been claimed over!");
4. Membuat catatan klaim:
struct receiveRecord record ; record.account = account; asset claimAmount = 0;
5. Perhitungan jumlah untuk setiap pemohon amplop.
Untuk peserta terakhir, jumlah sisanya ditentukan, untuk yang lain, jumlah yang dinyatakan ditentukan oleh angka acak yang dihitung dengan hash dari blok saat ini dan informasi terkini tentang amplop:
if (es.remainPackageCount == 1){ claimAmount = es.remainAmount; record.amount = claimAmount; }else{ H256 random = current_blockhash() ; char part[8]; memcpy(part,&random,8); uint64_t random_num = *(uint64_t*)part; uint32_t percent = random_num % 100 + 1; claimAmount = es.remainAmount * percent / 100;
6. Mengkredit dana
Jumlah token yang sesuai ditransfer ke akun pemohon amplop sesuai dengan hasil perhitungan:
address selfaddr = self_address(); if (isONTToken(es.tokenAddress)){ bool result = ont::transfer(selfaddr,account ,claimAmount); ontio_assert(result,"transfer ont token failed!"); } else if (isONGToken(es.tokenAddress)){ bool result = ong::transfer(selfaddr,account ,claimAmount); ontio_assert(result,"transfer ong token failed!"); } else{ std::vector<char> params = pack(std::string("transfer"),selfaddr,account,claimAmount); bool res = false; call_contract(es.tokenAddress,params, res ); ontio_assert(res,"transfer oep4 token failed!"); }
7. Kami akan menuliskan informasi tentang penerimaan dana dan informasi terbaru tentang amplop di lemari besi dan mengirimkan pemberitahuan tentang pemenuhan kontrak:
storage_put(claimkey,claimAmount); storage_put(rekey,es); char buffer [100]; std::sprintf(buffer, "{\"states\":[\"%s\",\"%s\",\"%s\",\"%lld\"]}","claimEnvlope",hash.c_str(),account.tohexstring().c_str(),claimAmount); notify(buffer); return true;
Seperti disebutkan di atas, kontrak ini dapat mengirim token dari kontrak melalui API claimEnvelope. Ini memastikan keamanan token saat berada di dalam amplop, karena tidak ada yang dapat menarik aset tanpa memenuhi persyaratan yang diperlukan.
Selesai! Anda menulis kontrak pintar pertama Anda. Kode kontrak lengkap dapat ditemukan di GitHub di
sini .
Pengujian kontrak
Ada dua cara untuk memverifikasi kontrak:
- Gunakan CLI
- Gunakan Golang SDK
Kesimpulan
Pada artikel ini, kami berbicara tentang cara menulis kontrak pintar untuk Ontolgy Wasm menggunakan API blockchain. Tetap menyelesaikan masalah privasi sehingga kontrak pintar berubah menjadi produk yang lengkap. Pada tahap kode ini, siapa pun bisa mendapatkan hash amplop merah dengan melacak catatan tentang kontrak, yang berarti bahwa siapa pun dapat mengklaim bagian dalam amplop. Masalah ini dapat diselesaikan dengan mudah - kami mendefinisikan daftar akun yang dapat mengajukan permohonan sebuah amplop ketika dibuat. Jika diinginkan, fungsi ini juga dapat diuji.
Dapatkan hibah Ontologi untuk pengembangan dApp mulai dari $ 20.000
Terapkan untuk Program Bakat Mahasiswa Ontologi
Apakah Anda seorang pengembang? Bergabunglah dengan komunitas teknologi kami di
Discord . Selain itu, lihat
Pusat Pengembang di situs web kami, tempat Anda dapat menemukan alat pengembang, dokumentasi, dan banyak lagi.
Ontologi