Terjemahan dan proofreading: "Komunitas Cina Starknet"
ringkasan
Kompiler Kairo versi 2 memperkenalkan perubahan pada sintaks Starknet untuk membuat kode lebih eksplisit dan aman. Antarmuka publik kontrak pintar ditentukan menggunakan sifat, dan akses ke penyimpanan dilakukan melalui sifat ContractState. Metode pribadi harus didefinisikan dengan implementasi yang berbeda dari antarmuka publik. Acara sekarang didefinisikan sebagai enum, di mana setiap varian adalah struct dengan nama yang sama.
Penafian: Istilah yang digunakan di sini mengacu pada versi yang berbeda dari kompiler Kairo, dan sintaksisnya bersifat sementara karena komunitas Starknet masih memperdebatkan istilah mana yang terbaik untuk digunakan. Setelah ditentukan, artikel ini akan diperbarui sebagaimana mestinya.
Kompiler v2
Baru minggu lalu, versi mayor baru 2.0.0-rc0 dari compiler Kairo dirilis di Github. Kompiler baru memberikan peningkatan signifikan pada plugin Starknet, membuat kode kami lebih aman, lebih eksplisit, dan lebih dapat digunakan kembali. Perhatikan bahwa versi baru kompiler ini belum didukung di Starknet testnet atau mainnet karena masih dikerjakan di lingkungan terintegrasi.
Tujuan artikel ini adalah untuk menunjukkan kepada Anda cara menulis ulang kontrak cerdas Starknet yang dibuat untuk kompiler Kairo versi 1.x menjadi kontrak cerdas yang kompatibel dengan kompiler versi 2.x. Titik awal kami adalah kontrak pintar yang Dapat Dimiliki yang dibuat di artikel sebelumnya, yang kompatibel dengan kompiler Cario versi 1.x.
[contract] mod Dapat Dimiliki {gunakan starknet::ContractAddress;gunakan starknet::get_caller_address;
Karena Protostar belum mendukung compiler v2, artikel ini akan bergantung pada pra-rilis Scarb (versi 0.5.0-alpha.1) yang mendukungnya. Untuk menginstal versi Scarb tertentu, Anda dapat menggunakan perintah berikut.
Setelah penyiapan selesai, kita dapat menuju ke src/lib.cairo dan mulai menulis kontrak pintar.
Penyimpanan dan konstruktor
Dalam compiler Kairo versi 2, smart contract masih ditentukan oleh modul yang dianotasi dengan atribut contract, hanya saja kali ini atribut tersebut diberi nama setelah plugin yang mendefinisikannya, dalam hal ini starknet.
#[starknet::contract]mod Dapat Dimiliki {}
Penyimpanan internal masih didefinisikan sebagai struktur yang harus disebut Penyimpanan, hanya saja kali ini harus dianotasi dengan atribut penyimpanan.
#[starknet::contract]mod Dapat Dimiliki {use super::ContractAddress; # [storage] struct Storage {pemilik: ContractAddress,
Untuk mendefinisikan konstruktor, kita menganotasi fungsi dengan atribut konstruktor, seperti yang kita lakukan di v1, keuntungannya adalah sekarang fungsi tersebut dapat memiliki nama apa saja, tidak perlu disebut "konstruktor" seperti di v1. Meskipun tidak wajib, saya masih akan menyebut fungsi tersebut sebagai "konstruktor" di luar konvensi, tetapi Anda dapat menyebutnya berbeda.
Perubahan penting lainnya adalah sekarang konstruktor secara otomatis meneruskan referensi ke ContractState, yang bertindak sebagai perantara untuk menyimpan variabel, dalam hal ini "pemilik".
Perhatikan bahwa sintaks untuk menulis dan membaca penyimpanan telah berubah sejak v1. Sebelum kita melakukan owner::write(), sekarang kita melakukan self.owner.write(). Hal yang sama berlaku untuk membaca dari penyimpanan.
Omong-omong, tipe ContractState tidak perlu dibawa ke ruang lingkup secara manual, itu termasuk dalam pendahuluan.
Metode Publik
Perbedaan penting dari compiler Kairo versi 1 adalah bahwa sekarang kita perlu secara eksplisit mendefinisikan antarmuka publik dari smart contract menggunakan ciri-ciri yang dianotasi dengan atribut starknet::interface.
Jika Anda mengingat kode asli dari v1, kontrak pintar kami memiliki dua metode "publik" (dapatkan_pemilik dan transfer_kepemilikan) dan satu metode "pribadi" (hanya_pemilik). Fitur ini hanya berurusan dengan metode publik, dan tidak bergantung pada atribut "eksternal" atau "tampilan" untuk menunjukkan metode mana yang dapat mengubah status kontrak dan metode mana yang tidak. Sebagai gantinya, ini sekarang dibuat eksplisit dengan tipe parameter self.
Jika suatu metode memerlukan referensi ke ContractStorage (yang, setelah diimplementasikan, T generik melakukannya), metode tersebut dapat mengubah keadaan internal kontrak cerdas. Inilah yang biasa kami sebut sebagai metode "eksternal". Di sisi lain, jika suatu metode memerlukan snapshot dari ContractStorage, ia hanya dapat membacanya, tidak dapat mengubahnya. Inilah yang biasa kami sebut metode "tampilan".
Kami sekarang dapat membuat implementasi untuk sifat yang baru saja kami definisikan menggunakan kata kunci impl. Ingat, Kairo berbeda dari Rust karena implementasinya memiliki nama.
Kami membuat implementasi untuk sifat kami di dalam modul yang mendefinisikan smart contract, meneruskan tipe ContractState sebagai tipe umum T sehingga penyimpanan dapat diakses seperti konstruktor.
Implementasi kami dianotasi dengan atribut external(v0). Versi 0 dalam atribut berarti pemilih hanya berasal dari nama metode, seperti yang terjadi di masa lalu. Sisi negatifnya adalah jika Anda menentukan implementasi lain dari sifat yang berbeda untuk kontrak pintar Anda, dan dua sifat kebetulan menggunakan nama yang sama untuk salah satu metode mereka, kompiler akan membuat kesalahan karena pemilih duplikat.
Versi mendatang dari properti ini mungkin menambahkan cara baru untuk mengevaluasi penyeleksi untuk mencegah konflik, tetapi itu belum berhasil. Saat ini, kami hanya dapat menggunakan properti eksternal versi 0.
Metode Pribadi
Kita juga perlu menentukan metode lain untuk smart contract, hanya_owner. Metode ini memeriksa apakah orang yang memanggilnya adalah pemilik smart contract.
Karena ini adalah metode privat yang tidak boleh dipanggil dari luar, metode ini tidak dapat didefinisikan sebagai bagian dari OwnableTrait (antarmuka publik dari smart contract). Sebagai gantinya, kami akan menggunakan atribut generate_trait untuk membuat implementasi baru dari sifat yang dibuat secara otomatis.
...#[starknet::contract]mod Dapat Dimiliki { ... #[generate_trait] impl PrivateMethods of PrivateMethodsTrait { fn only_owner(self: @ContractState) { let caller = get_caller_address(); menegaskan(penelepon == self.owner.read(), 'Penelepon bukan pemilik'); }
Metode only_owner sekarang dapat digunakan dengan memanggil self.only_owner() jika diperlukan.
#[starknet::contract]mod Dapat Dimiliki { ... #[eksternal(v0)] impl OwnableImpl dari super::OwnableTrait { fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { self.only_owner (); ... } ... }
Di Kairo v1, sebuah acara hanyalah sebuah fungsi tanpa badan dan dianotasi dengan atribut acara, sedangkan di v2 sebuah acara adalah sebuah enum yang dianotasi dengan atribut yang sama, tetapi sekarang diimplementasikan menggunakan beberapa fitur tambahan.
...#[starknet::contract]mod Dapat Dimiliki { ... # [event] #[derive(Lepaskan, starknet::Event)] enum Acara { KepemilikanDitransfer: KepemilikanDitransfer, }
Setiap varian dari event enum harus berupa struct dengan nama yang sama. Dalam struktur ini, kami menggunakan atribut kunci opsional untuk menentukan semua nilai yang ingin kami pancarkan, untuk memberi tahu sistem nilai mana yang ingin kami indeks Starknet, sehingga pengindeks dapat mencari dan mengambil lebih cepat. Dalam hal ini, kami ingin mengindeks dua nilai (prev_owner dan new_owner).
Sifat ContractState mendefinisikan metode emisi yang dapat digunakan untuk memancarkan peristiwa.
...#[starknet::contract]mod Dapat Dimiliki { ... #[eksternal(v0)] impl OwnableImpl dari super::OwnableTrait { fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { .. .self.emit(Event::OwnershipTransferred(OwnershipTransferred { prev_owner: prev_owner, new_owner: new_owner, })); } ... } ...}
Dengan fitur terakhir ini, kami telah menyelesaikan migrasi smart contract yang Dapat Dimiliki dari v1 ke v2. Kode lengkap ditunjukkan di bawah ini.
#[generate_trait] impl PrivateMethods of PrivateMethodsTrait { fn only_owner(self: @ContractState) { let caller = get_caller_address(); menegaskan(penelepon == self.owner.read(), 'Penelepon bukan pemilik'); }
Anda juga dapat menemukan kode ini di Github.
Kesimpulannya
Kompiler Kairo versi 2 membawa sintaks baru ke Starknet yang membuat kode kontrak pintar terlihat lebih konsisten dengan Kairo itu sendiri dan, dengan ekstensi, lebih mirip Rust. Bahkan dengan mengorbankan kode yang lebih rumit, manfaat keamanannya sepadan dengan pengorbanannya.
Pada artikel ini, kami belum menyentuh semua tentang sintaks baru, terutama bagaimana interaksinya dengan smart contract lainnya, tetapi Anda dapat membaca log perubahan kompiler, membaca postingan ini di forum, atau menonton video di saluran YouTube StarkWare untuk mempelajari lebih lanjut tentang hal itu untuk mengetahui informasi lebih lanjut.
Versi baru kompiler ini akan tersedia di testnet Starknet dalam beberapa minggu dan mainnet dalam beberapa minggu, jadi jangan mencoba menerapkan kode ini dulu, ini belum akan berfungsi.
Kairo terus menjadi lebih baik.
sumber
Sintaks Kontrak - Panduan Migrasi
Kairo 1: sintaksis kontrak berkembang
Lihat Asli
This page may contain third-party content, which is provided for information purposes only (not representations/warranties) and should not be considered as an endorsement of its views by Gate, nor as financial or professional advice. See Disclaimer for details.
Interpretasi Penuh Tata Bahasa Starknet yang Ditingkatkan
Asli: Peningkatan Sintaks Starknet
Terjemahan dan proofreading: "Komunitas Cina Starknet"
ringkasan
Kompiler Kairo versi 2 memperkenalkan perubahan pada sintaks Starknet untuk membuat kode lebih eksplisit dan aman. Antarmuka publik kontrak pintar ditentukan menggunakan sifat, dan akses ke penyimpanan dilakukan melalui sifat ContractState. Metode pribadi harus didefinisikan dengan implementasi yang berbeda dari antarmuka publik. Acara sekarang didefinisikan sebagai enum, di mana setiap varian adalah struct dengan nama yang sama.
Penafian: Istilah yang digunakan di sini mengacu pada versi yang berbeda dari kompiler Kairo, dan sintaksisnya bersifat sementara karena komunitas Starknet masih memperdebatkan istilah mana yang terbaik untuk digunakan. Setelah ditentukan, artikel ini akan diperbarui sebagaimana mestinya.
Kompiler v2
Baru minggu lalu, versi mayor baru 2.0.0-rc0 dari compiler Kairo dirilis di Github. Kompiler baru memberikan peningkatan signifikan pada plugin Starknet, membuat kode kami lebih aman, lebih eksplisit, dan lebih dapat digunakan kembali. Perhatikan bahwa versi baru kompiler ini belum didukung di Starknet testnet atau mainnet karena masih dikerjakan di lingkungan terintegrasi.
Tujuan artikel ini adalah untuk menunjukkan kepada Anda cara menulis ulang kontrak cerdas Starknet yang dibuat untuk kompiler Kairo versi 1.x menjadi kontrak cerdas yang kompatibel dengan kompiler versi 2.x. Titik awal kami adalah kontrak pintar yang Dapat Dimiliki yang dibuat di artikel sebelumnya, yang kompatibel dengan kompiler Cario versi 1.x.
[contract] mod Dapat Dimiliki {gunakan starknet::ContractAddress;gunakan starknet::get_caller_address;
[event] fn KepemilikanDitransfer(sebelumnya_pemilik: Alamat Kontrak, pemilik_baru: Alamat Kontrak) {}
struct Storage {pemilik: ContractAddress,}
[constructor] fn constructor() {biarkan deployer = get_caller_address();owner::write(deployer);}
[view] fn get_owner() -> ContractAddress {pemilik::baca()}
[external] fn transfer_kepemilikan(baru_pemilik: Alamat Kontrak) {hanya_pemilik();biarkan sebelumnya_pemilik = pemilik::baca();pemilik::tulis(baru_pemilik);KepemilikanDitransfer(sebelumnya_pemilik, pemilik_baru) ;}
fn only_owner() {let caller = get_caller_address();assert(caller == owner::read(), 'Penelepon bukan pemilik');
Pengaturan Proyek
Karena Protostar belum mendukung compiler v2, artikel ini akan bergantung pada pra-rilis Scarb (versi 0.5.0-alpha.1) yang mendukungnya. Untuk menginstal versi Scarb tertentu, Anda dapat menggunakan perintah berikut.
$ --proto '=https' --tlsv1.2 -sSf | bash -s -- -v 0.5.0-alpha.1
Setelah penginstalan selesai, verifikasi bahwa Anda memiliki versi yang benar.
$ scarb --version>>>scarb 0.5.0-alpha.1 (546dad33d 2023-06-19)cairo:2.0.0-rc3()
Proyek Scarb sekarang dapat dibuat.
$ scarb new kairo1_v2$cdcairo1_v2
Anda harus mendapatkan struktur folder seperti di bawah ini.
$ pohon .>>>.├── Scarb.toml└── src└──lib.cairo
Agar Scarb dapat mengkompilasi kontrak pintar Starknet, plugin Starknet harus diaktifkan sebagai ketergantungan.
// Scarb.toml... [dependencies] starknet="2.0.0-rc3"
Setelah penyiapan selesai, kita dapat menuju ke src/lib.cairo dan mulai menulis kontrak pintar.
Penyimpanan dan konstruktor
Dalam compiler Kairo versi 2, smart contract masih ditentukan oleh modul yang dianotasi dengan atribut contract, hanya saja kali ini atribut tersebut diberi nama setelah plugin yang mendefinisikannya, dalam hal ini starknet.
#[starknet::contract]mod Dapat Dimiliki {}
Penyimpanan internal masih didefinisikan sebagai struktur yang harus disebut Penyimpanan, hanya saja kali ini harus dianotasi dengan atribut penyimpanan.
#[starknet::contract]mod Dapat Dimiliki {use super::ContractAddress; # [storage] struct Storage {pemilik: ContractAddress,
Untuk mendefinisikan konstruktor, kita menganotasi fungsi dengan atribut konstruktor, seperti yang kita lakukan di v1, keuntungannya adalah sekarang fungsi tersebut dapat memiliki nama apa saja, tidak perlu disebut "konstruktor" seperti di v1. Meskipun tidak wajib, saya masih akan menyebut fungsi tersebut sebagai "konstruktor" di luar konvensi, tetapi Anda dapat menyebutnya berbeda.
Perubahan penting lainnya adalah sekarang konstruktor secara otomatis meneruskan referensi ke ContractState, yang bertindak sebagai perantara untuk menyimpan variabel, dalam hal ini "pemilik".
#[starknet::contract]mod Dapat Dimiliki {use super::ContractAddress; # [storage] struct Storage {pemilik: ContractAddress,} # [constructor] fn constructor(ref self: ContractState) {let deployer = get_caller_address();self.owner.write(deployer);
Perhatikan bahwa sintaks untuk menulis dan membaca penyimpanan telah berubah sejak v1. Sebelum kita melakukan owner::write(), sekarang kita melakukan self.owner.write(). Hal yang sama berlaku untuk membaca dari penyimpanan.
Omong-omong, tipe ContractState tidak perlu dibawa ke ruang lingkup secara manual, itu termasuk dalam pendahuluan.
Metode Publik
Perbedaan penting dari compiler Kairo versi 1 adalah bahwa sekarang kita perlu secara eksplisit mendefinisikan antarmuka publik dari smart contract menggunakan ciri-ciri yang dianotasi dengan atribut starknet::interface.
gunakan starknet::ContractAddress;
#[starknet::interface]trait OwnableTrait { fn transfer_ownership(ref self: T, new_owner: ContractAddress); fn get_owner(self: @T) -> ContractAddress;}
#[starknet::contract]mod Dapat Dimiliki { ...}
Jika Anda mengingat kode asli dari v1, kontrak pintar kami memiliki dua metode "publik" (dapatkan_pemilik dan transfer_kepemilikan) dan satu metode "pribadi" (hanya_pemilik). Fitur ini hanya berurusan dengan metode publik, dan tidak bergantung pada atribut "eksternal" atau "tampilan" untuk menunjukkan metode mana yang dapat mengubah status kontrak dan metode mana yang tidak. Sebagai gantinya, ini sekarang dibuat eksplisit dengan tipe parameter self.
Jika suatu metode memerlukan referensi ke ContractStorage (yang, setelah diimplementasikan, T generik melakukannya), metode tersebut dapat mengubah keadaan internal kontrak cerdas. Inilah yang biasa kami sebut sebagai metode "eksternal". Di sisi lain, jika suatu metode memerlukan snapshot dari ContractStorage, ia hanya dapat membacanya, tidak dapat mengubahnya. Inilah yang biasa kami sebut metode "tampilan".
Kami sekarang dapat membuat implementasi untuk sifat yang baru saja kami definisikan menggunakan kata kunci impl. Ingat, Kairo berbeda dari Rust karena implementasinya memiliki nama.
gunakan starknet::ContractAddress;
#[starknet::interface]trait OwnableTrait { fn transfer_ownership(ref self: T, new_owner: ContractAddress); fn get_owner(self: @T) -> ContractAddress;}
#[starknet::contract]mod Dapat Dimiliki { ... #[eksternal(v0)] impl OwnableImpl dari super::OwnableTrait { fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { let prev_owner = self.owner.read(); self.owner.write(new_owner); }
fn get_owner(self: @ContractState) -> ContractAddress { self.owner.read() }
Kami membuat implementasi untuk sifat kami di dalam modul yang mendefinisikan smart contract, meneruskan tipe ContractState sebagai tipe umum T sehingga penyimpanan dapat diakses seperti konstruktor.
Implementasi kami dianotasi dengan atribut external(v0). Versi 0 dalam atribut berarti pemilih hanya berasal dari nama metode, seperti yang terjadi di masa lalu. Sisi negatifnya adalah jika Anda menentukan implementasi lain dari sifat yang berbeda untuk kontrak pintar Anda, dan dua sifat kebetulan menggunakan nama yang sama untuk salah satu metode mereka, kompiler akan membuat kesalahan karena pemilih duplikat.
Versi mendatang dari properti ini mungkin menambahkan cara baru untuk mengevaluasi penyeleksi untuk mencegah konflik, tetapi itu belum berhasil. Saat ini, kami hanya dapat menggunakan properti eksternal versi 0.
Metode Pribadi
Kita juga perlu menentukan metode lain untuk smart contract, hanya_owner. Metode ini memeriksa apakah orang yang memanggilnya adalah pemilik smart contract.
Karena ini adalah metode privat yang tidak boleh dipanggil dari luar, metode ini tidak dapat didefinisikan sebagai bagian dari OwnableTrait (antarmuka publik dari smart contract). Sebagai gantinya, kami akan menggunakan atribut generate_trait untuk membuat implementasi baru dari sifat yang dibuat secara otomatis.
...#[starknet::contract]mod Dapat Dimiliki { ... #[generate_trait] impl PrivateMethods of PrivateMethodsTrait { fn only_owner(self: @ContractState) { let caller = get_caller_address(); menegaskan(penelepon == self.owner.read(), 'Penelepon bukan pemilik'); }
Metode only_owner sekarang dapat digunakan dengan memanggil self.only_owner() jika diperlukan.
#[starknet::contract]mod Dapat Dimiliki { ... #[eksternal(v0)] impl OwnableImpl dari super::OwnableTrait { fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { self.only_owner (); ... } ... }
#[generate_trait] impl PrivateMethods of PrivateMethodsTrait { fn only_owner(self: @ContractState) { ... }
peristiwa
Di Kairo v1, sebuah acara hanyalah sebuah fungsi tanpa badan dan dianotasi dengan atribut acara, sedangkan di v2 sebuah acara adalah sebuah enum yang dianotasi dengan atribut yang sama, tetapi sekarang diimplementasikan menggunakan beberapa fitur tambahan.
...#[starknet::contract]mod Dapat Dimiliki { ... # [event] #[derive(Lepaskan, starknet::Event)] enum Acara { KepemilikanDitransfer: KepemilikanDitransfer, }
#[derive(Lepaskan, starknet::Event)] struct KepemilikanDitransfer { # [key] prev_owner: Alamat Kontrak, # [key] pemilik_baru: Alamat Kontrak,
Setiap varian dari event enum harus berupa struct dengan nama yang sama. Dalam struktur ini, kami menggunakan atribut kunci opsional untuk menentukan semua nilai yang ingin kami pancarkan, untuk memberi tahu sistem nilai mana yang ingin kami indeks Starknet, sehingga pengindeks dapat mencari dan mengambil lebih cepat. Dalam hal ini, kami ingin mengindeks dua nilai (prev_owner dan new_owner).
Sifat ContractState mendefinisikan metode emisi yang dapat digunakan untuk memancarkan peristiwa.
...#[starknet::contract]mod Dapat Dimiliki { ... #[eksternal(v0)] impl OwnableImpl dari super::OwnableTrait { fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { .. .self.emit(Event::OwnershipTransferred(OwnershipTransferred { prev_owner: prev_owner, new_owner: new_owner, })); } ... } ...}
Dengan fitur terakhir ini, kami telah menyelesaikan migrasi smart contract yang Dapat Dimiliki dari v1 ke v2. Kode lengkap ditunjukkan di bawah ini.
gunakan starknet::ContractAddress;
#[starknet::interface]trait OwnableTrait { fn transfer_ownership(ref self: T, new_owner: ContractAddress); fn get_owner(self: @T) -> ContractAddress;}
#[starknet::contract]mod Dapat Dimiliki { gunakan super::ContractAddress; gunakan starknet::get_caller_address;
[event] #[derive(Lepaskan, starknet::Event)] enum Acara { KepemilikanDitransfer: KepemilikanDitransfer, }
#[derive(Lepaskan, starknet::Event)] struct KepemilikanDitransfer { # [key] prev_owner: Alamat Kontrak, # [key] baru_pemilik: Alamat Kontrak, }
[storage] struct Penyimpanan { pemilik: Alamat Kontrak, }
[constructor] fn constructor(ref self: ContractState) { let deployer = get_caller_address(); self.owner.write(deployer); }
#[external(v0)] impl OwnableImpl of super::OwnableTrait { fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) { self.only_owner(); biarkan prev_owner = self.owner.read(); self.owner.write(new_owner); self.emit(Event::OwnershipTransferred(OwnershipTransferred { prev_owner: prev_owner, new_owner: new_owner, })); }
fn get_owner(self: @ContractState) -> ContractAddress { self.owner.read() } }
#[generate_trait] impl PrivateMethods of PrivateMethodsTrait { fn only_owner(self: @ContractState) { let caller = get_caller_address(); menegaskan(penelepon == self.owner.read(), 'Penelepon bukan pemilik'); }
Anda juga dapat menemukan kode ini di Github.
Kesimpulannya
Kompiler Kairo versi 2 membawa sintaks baru ke Starknet yang membuat kode kontrak pintar terlihat lebih konsisten dengan Kairo itu sendiri dan, dengan ekstensi, lebih mirip Rust. Bahkan dengan mengorbankan kode yang lebih rumit, manfaat keamanannya sepadan dengan pengorbanannya.
Pada artikel ini, kami belum menyentuh semua tentang sintaks baru, terutama bagaimana interaksinya dengan smart contract lainnya, tetapi Anda dapat membaca log perubahan kompiler, membaca postingan ini di forum, atau menonton video di saluran YouTube StarkWare untuk mempelajari lebih lanjut tentang hal itu untuk mengetahui informasi lebih lanjut.
Versi baru kompiler ini akan tersedia di testnet Starknet dalam beberapa minggu dan mainnet dalam beberapa minggu, jadi jangan mencoba menerapkan kode ini dulu, ini belum akan berfungsi.
Kairo terus menjadi lebih baik.
sumber