本記事は、ガイドについての日本語翻訳です。
Aleph Zero スマートコントラクトの基礎
開発者の皆様には、Aleph Zero テストネットのスマート コントラクト機能をぜひお試しください。このガイドでは、開始方法について説明します。
この短いチュートリアルでは、Aleph Zero Testnet のスマート コントラクト機能の基本について説明します。
次のページでは、テストネット アカウントの設定方法、スマート コントラクト開発用にコンピューターを準備する方法、スマート コントラクトの作成、コンパイル、デプロイの方法、そして最後にデプロイしたスマート コントラクトとやり取りする方法について説明します。注: スマート コントラクトは現在、Aleph Zero メインネットで稼働しています。
テストネットアカウントの設定
テストネットの操作について知っておくべきことはすべてここにあります。ここでは、このテスト環境を活用するために必要な 2 つの重要なコンポーネントについて説明します。
Aleph Zero Testnet アカウントを設定するには、次の 2 つのコンポーネントを使用する必要があります。
- アカウントを作成し、後でスマート コントラクトをデプロイして操作できるテストネット ウォレット/エクスプローラー。
- Testnet Faucetでは、Aleph Zero Testnet とやり取りし、スマート コントラクトの開発を試すために必要な無料の TZERO トークンを受け取ることができます。
必要な手順は簡単です
- Testnet ウォレットの[アカウント] タブを開き、画面の指示に従ってアカウントを追加します。
- 新しく作成したアカウントのコインを受け取るには、 Testnet Faucetを使用します。アカウント アドレスをコピーして Faucet に貼り付けるだけです。TZERO はほぼ瞬時に利用できるようになります。エクスプローラーでタブに戻って確認する前には、確実に利用できます
必要なツールのインストール
Aleph Zero で最初のスマート コントラクトを実行する前に、まず Rust と ink! での開発用にコンピューターを準備する必要があります。こちらに、開始するための便利なガイドがあります。
Aleph Zero テストネットに最初のスマート コントラクトをデプロイする前に最初に行う必要があるのは、Rust と ink! での開発用にコンピューターを準備することです。
Rust
このガイドでは、https://rustup.rsインストーラーとrustup
Rust ツールチェーンを管理するツールを使用します。これは Rust をインストールするデフォルトの方法であり、この方法を使用することを強くお勧めします。ただし、別の方法を希望する場合は、公式Rust Web サイトの「その他のインストール方法」セクションを確認してください。
インストールして設定するには、rustup
シェルで次のコマンドを入力します。
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
これで、最新の安定バージョンの Rust がコンピューターにインストールされました。スマート コントラクトの開発には、もう少し新しいnightly
バージョンと、いくつかの追加コンポーネントが必要になります。
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
Rust にはネイティブ パッケージ マネージャーが付属しておりcargo
、Rust コードのコンパイルにも使用されます。cargo
正しくインストールされ、シェル環境で表示されていることを確認してください。
cargo --help
ink!
ink! は、WASM スマート コントラクトを Rust で記述するために使用できる組み込みドメイン固有言語(EDSL)です。言い換えると、ink! は Rust 上の「アドオン」のコレクションであり、言語の動作を変更して、コンピューターで実行できる通常のバイナリ コードではなく、Substrate ベースのスマート コントラクト実行環境と互換性のある特別な WASM コードを生成します。結局のところ、すべての ink! スマート コントラクトは、通常の Rust プログラムに「マクロ」と呼ばれる ink! 固有のヘッダーが少し追加されただけです。
binaryen
ink! の使用を開始するには、まず、コントラクトの WebAssembly バイトコードを最適化するために使用されるパッケージをインストールする必要があります。ほとんどの場合、binaryen
デフォルトのパッケージ マネージャーから入手できます。
# For Ubuntu or Debian users:
sudo apt install binaryen
# For MacOS users:
brew install binaryen
# For Arch or Manjaro users:
pacman -S binaryen
バイナリリリースを直接ダウンロードすることもできます。
現在binaryen
、インストールできるもの cargo contract
:
cargo install --force --locked cargo-contract
cargo contract
は、スマート コントラクトの開発に役立つコマンドで を拡張するアドオンですcargo
。 を呼び出すことで、何ができるかを確認できますcargo contract --help
。すぐにこれを使用して、最初の ink! スマート コントラクトを作成します。
最初の契約書を作成する
これでマシンの開発準備が整いましたので、最初のスマート コントラクトを構築します。このチュートリアルで開発するサンプル コントラクトは、ERC20 トークンの簡易バージョンです。
導入
重要なツールがすべて揃ったら、最初の ink! スマート コントラクトを開発する準備が整いました。
このチュートリアルで構築するサンプル コントラクトは、ERC20トークンの非常にシンプルなバージョンです。コントラクトをインスタンス化すると、アカウント間で転送できる新しいタイプの代替可能なトークンを含むプールが作成されます。コントラクトは、アカウントの残高のレジストリを保持し、残高を照会してトークンを転送するメソッドを提供します。
契約書の作成
まず、次のものを使用して契約テンプレートを生成しますcargo contract
。
cargo contract new mytoken
cd mytoken
mytoken
このコマンドは、次のファイルを含む新しいディレクトリを作成します。
lib.rs
– 契約のコードを含むRustソースファイルCargo.toml
cargo
-コントラクトの構築方法を説明するマニフェスト ファイル(このチュートリアルでは変更する必要はありません).gitignore
git
-契約書のバージョン管理に使用する場合
のみを扱いますlib.rs
。残りの 2 つのファイルはそのままにしておきます。中を見ると、lib.rs
最も単純な hello-world コントラクトであるフリッパーが見つかります。これは、単一のブール値を保持し、それを反転できるものです。コードを確認することをお勧めしますが、一部が不可解に思えても心配しないでください。コードを段階的に変更し、その過程ですべてを説明します。
実装
ink! で書かれたスマート コントラクトは、実際には ink! マクロ ( のような行#[ink...]
) を使用する通常の Rust コードです。これらのマクロの役割は、コンパイル プロセスを変更して、コンピューターで実行できる通常のプログラムではなく、Aleph Zero ブロックチェーンにデプロイできる WASM スマート コントラクトを生成することです。ファイルの上部に、構成マクロを含める必要があります。
#![cfg_attr(not(feature = "std"), no_std, no_main)]
この恐ろしそうなマクロは、基本的にコンパイラに標準ライブラリを含めないように指示します (ink! はスマート コントラクト開発に適した独自のプリミティブ セットを使用します)。また、main
シンボルの発行を無効にすることもできます。ファイルの残りの部分には、メインの ink! マクロがプレフィックスとして付いたモジュールの定義が含まれています。
#[ink::contract]
mod mytoken {
//...
}
このマクロは、モジュールがmytoken
実際にはスマート コントラクトの定義であり、ink! がそのモジュール内でコントラクトのさまざまなコンポーネントを調べる必要があることを ink! に伝えます。またBalance
、 やなどの便利な型エイリアスも提供しますAccount
。さらに、現時点では気にする必要のない不変条件をいくつか強制します。
- 契約には、次のようにマークされた構造体が1つだけ必要です。
#[ink::storage]
- 契約には少なくとも1つの機能がマークされている必要があります。
#[ink::constructor]
ストレージ
最初のコンポーネントは、コントラクト ストレージです。ブロックチェーンに保存され、コントラクトの状態を保持するデータが含まれています。この場合、これはユーザーと所有するトークンの数のマッピングと、総供給量または新しいトークンを保持する単一の数値になります。そのデータは、struct
対応する ink! ストレージ マクロをプレフィックスとして付けた単一の Rust で囲む必要があります。
#[ink::contract]
mod mytoken {
use ink::storage::Mapping;
#[ink(storage)]
#[derive(Default)]
pub struct Mytoken {
total_supply: Balance,
balances: Mapping<AccountId, Balance>,
}
}
Mapping
ここでは、クレートによって提供されるデータ構造
を使用していますink::storage
。ink! スマート コントラクトを作成する場合、Rust 標準ライブラリのデータ構造は使用できないことに注意してください。幸いなことに、ink! は、オンチェーンで保存できるように最適化されたキー値マップの形式で、
便利な代替手段を提供します。
ink! に特性の実装を作成するように指示していることにも注意してくださいDefault
。この場合、コンパイラはフィールドtotal_supply
を 0 ( Default
a の値Balance
) に初期化し、をbalances
空Mapping
(偶然にも対応するDefault
実装) に初期化できます。
コンストラクタ
次のステップは、コントラクトのコンストラクタを実装することです。これは、impl
新しく定義されstruct Mytoken
、適切な ink! マクロをプレフィックスとして付けたブロック内に配置する必要があり、
コントラクトには、それぞれがマクロでマークされている限り、任意の数の 0 以外のコンストラクタを含めることができます#[ink(constructor)]
。
#[ink::contract]
mod mytoken {
// ... (storage definition)
impl Mytoken {
#[ink(constructor)]
pub fn new(total_supply: Balance) -> Self {
let mut balances = Mapping::default();
let caller = Self::env().caller();
balances.insert(caller, &total_supply);
Self {
total_supply,
balances,
}
}
}
}
コンストラクターは、新しく作成されたトークンの初期供給量という単一の引数を受け取り、その供給量すべてをコントラクト作成者のアカウント (コンストラクターを呼び出すアカウント) に預け入れます。
コントラクトのコンストラクターは、通常の Rust コンストラクターと非常によく似ています。最初に関数を呼び出してstruct
空を作成し、その後で最初のエントリを挿入して、すべての供給をコンストラクターの呼び出し元に割り当てることに注意してください。Mapping
Default::default()
Self::env().caller()
メソッドを使用して、コントラクトを呼び出したアカウントのアドレスにアクセスできます。コンストラクターのコンテキストでは、これはコントラクトの作成者/所有者になります。
メッセージ
上記で定義したコントラクト のコンストラクターが実際には ink! マクロがプレフィックスとして付けられた通常の Rust コンストラクターであるのと同様に、コントラクトの呼び出し可能メソッド ( ink! によってメッセージと呼ばれる) は、別の ink! マクロで注釈が付けられた通常の Rust メソッドです。
#[ink::contract]
mod mytoken {
// ... (storage definition)
impl Mytoken {
// ... (constructor definition)
#[ink(message)]
pub fn total_supply(&self) -> Balance {
self.total_supply
}
#[ink(message)]
pub fn balance_of(&self, account: AccountId) -> Balance {
self.balances.get(&account).unwrap_or_default()
}
}
}
ここでは、契約のストレージにアクセスするための 2 つのメソッドを定義しました。合計供給量と特定のアカウントが保持するトークンの数を読み取るメソッドです。これらのメソッドは読み取り専用であり、契約ストレージを変更せず、ブロックチェーンにトランザクションを送信せずに呼び出すことができます。
メソッドは、まず指定された のマッピングbalance_of
から値を取得します。結果は構造体にラップされて返されます。メソッドを使用して、実際の値または型のデフォルト(便利なことに 0) を取得します。balances
account
Option
unwrap_or_default()
Balance
エラー
関数を見る前にtransfer
、Rust のエラー処理の慣用的な方法を学ぶ必要があります。一部の言語とは対照的に、Rust は例外の概念を捨てて代数的なエラー処理を採用しています。失敗する可能性のある各メソッドにはResult<T, E>
型があり、次のように定義されます。コピー
pub enum Result<T, E> {
Ok(val: T), // T is the expected type of the computation
Err(msg: E), // E is an error type of your choice
}
私たちの契約では、の一部Error
として使用するカスタム構造体を定義します。Err
Result
コピー
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
InsufficientBalance,
}
この入門チュートリアルでは、恐ろしいマクロについては心配しないでください。後のチュートリアルで詳しく説明します。今のところは、それらをコピーするだけで十分です😊以下の実装ではtransfer
、実際にこのメソッドを使用する例がわかります。
最後に必要なのは、アカウント間でトークンを転送する方法です。
mod mytoken {
// ...
impl Mytoken {
// ... constructor definition
// ... error definition
#[ink(message)]
pub fn transfer(&mut self, to: AccountId, value: Balance) -> Result<(), Error> {
let from = self.env().caller();
let from_balance = self.balance_of(from);
if from_balance < value {
return Err(Error::InsufficientBalance);
}
self.balances.insert(from, &(from_balance - value));
let to_balance = self.balance_of(to);
self.balances.insert(to, &(to_balance + value));
Ok(())
}
}
}
このメソッドは、任意のユーザーが呼び出して、amount
自分のトークンの一部を自分の選択した に転送することができますrecipient
。ユーザーが所有するトークンよりも多くのトークンを転送しようとすると、メソッドは変更を実行せずに終了します。transfer
メソッド内では、以前に定義した メソッドを使用していることに注意してくださいbalance_of
。
transfer
この方法と以前の方法の最も重要な違いは、 がコントラクト ストレージを変更するという事実です。 この事実は、最初の引数として&mut self
ではなくを使用して示す必要があります&self
。 この要件はコンパイラによって強制されます。 を忘れた場合mut
、コントラクトはビルドされず、コンパイラは を使用するように提案しますmut
。 したがって、バグのあるコントラクトをデプロイすることを心配する必要はありません。
テスト
他のすべてのプログラムと同様に、スマート コントラクトもテストする必要があります。開発プロセスのこの部分も、通常の Rust で行われる方法と非常に似ています。テストはオフチェーンで実行され、ink! は、将来コントラクトが稼働するオンチェーン環境をシミュレートするのに役立つ便利なツールをいくつか提供します。
ここでは、実装された各メソッドの基本的な健全性チェックを含む非常に最小限のテスト スイートを示します。次のコードは、lib.rs
コントラクトと同じファイルに配置する必要があります。
#[cfg(test)]
mod tests {
use super::*;
#[ink::test]
fn total_supply_works() {
let mytoken = Mytoken::new(100);
assert_eq!(mytoken.total_supply(), 100);
}
#[ink::test]
fn balance_of_works() {
let mytoken = Mytoken::new(100);
let accounts =
ink::env::test::default_accounts::<ink::env::DefaultEnvironment>();
assert_eq!(mytoken.balance_of(accounts.alice), 100);
assert_eq!(mytoken.balance_of(accounts.bob), 0);
}
#[ink::test]
fn transfer_works() {
let mut mytoken = Mytoken::new(100);
let accounts =
ink::env::test::default_accounts::<ink::env::DefaultEnvironment>();
assert_eq!(mytoken.balance_of(accounts.bob), 0);
assert_eq!(mytoken.transfer(accounts.bob, 10), Ok(()));
assert_eq!(mytoken.balance_of(accounts.bob), 10);
}
}
上記のコントラクトを実装すると、このコードの詳細については説明を要しません。
テスト スイートは、フォルダーcargo test
内でターミナルを呼び出すことによって実行できますmytoken
。
cargo test
Compiling mytoken v0.1.0 (/home/user/ink/mytoken)
Finished test [unoptimized + debuginfo] target(s) in 1.08s
Running unittests lib.rs (target/debug/deps/mytoken-668aad4b5e4b8a01)
running 3 tests
test tests::balance_of_works ... ok
test tests::total_supply_works ... ok
test tests::transfer_works ... ok
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0
ink! のバージョン 4.0 では、スマート コントラクト開発フローにエンドツーエンドのテストが導入されました。これについては、コントラクトの正確性を確保するための推奨される追加の方法として、後のチュートリアルで説明します。
まとめ
最後に、契約のすべての部分を最終バージョンに組み合わせましょう。///...
これらの部分の機能を説明するドキュメントコメント ( ) を追加することもできます。ここでは簡潔にするために省略していますが、含めることをお勧めします。この情報は、契約 UI を通じて契約を操作するユーザーに表示されます。mytoken/lib.rs
#![cfg_attr(not(feature = "std"), no_std, no_main)]
#[ink::contract]
mod mytoken {
use ink::storage::Mapping;
#[ink(storage)]
#[derive(Default)]
pub struct Mytoken {
total_supply: Balance,
balances: Mapping<AccountId, Balance>,
}
#[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
InsufficientBalance,
}
impl Mytoken {
#[ink(constructor)]
pub fn new(total_supply: Balance) -> Self {
let mut balances = Mapping::default();
let caller = Self::env().caller();
balances.insert(caller, &total_supply);
Self {
total_supply,
balances,
}
}
#[ink(message)]
pub fn total_supply(&self) -> Balance {
self.total_supply
}
#[ink(message)]
pub fn balance_of(&self, owner: AccountId) -> Balance {
self.balances.get(owner).unwrap_or_default()
}
#[ink(message)]
pub fn transfer(&mut self, to: AccountId, value: Balance) -> Result<(), Error> {
let from = self.env().caller();
let from_balance = self.balance_of(from);
if from_balance < value {
return Err(Error::InsufficientBalance);
}
self.balances.insert(from, &(from_balance - value));
let to_balance = self.balance_of(to);
self.balances.insert(to, &(to_balance + value));
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[ink::test]
fn total_supply_works() {
let mytoken = Mytoken::new(100);
assert_eq!(mytoken.total_supply(), 100);
}
#[ink::test]
fn balance_of_works() {
let mytoken = Mytoken::new(100);
let accounts =
ink::env::test::default_accounts::<ink::env::DefaultEnvironment>();
assert_eq!(mytoken.balance_of(accounts.alice), 100);
assert_eq!(mytoken.balance_of(accounts.bob), 0);
}
#[ink::test]
fn transfer_works() {
let mut mytoken = Mytoken::new(100);
let accounts =
ink::env::test::default_accounts::<ink::env::DefaultEnvironment>();
assert_eq!(mytoken.balance_of(accounts.bob), 0);
assert_eq!(mytoken.transfer(accounts.bob, 10), Ok(()));
assert_eq!(mytoken.balance_of(accounts.bob), 10);
}
}
}
コンパイル
次は契約を構築します。
cargo +nightly contract build --release
結果のファイルはmytoken/target/ink/
フォルダーに配置されます。コンパイルが成功すると、次の 3 つのファイルが見つかります。
mytoken.wasm
コンパイルされた契約を含むバイナリWASMファイルですmetadata.json
契約ABI(アプリケーションバイナリインターフェース)を含むmytoken.contract
上記2つをバンドルして、チェーンエクスプローラーとのより便利なやり取りを実現します。
mytoken
これで、 Aleph Zero Testnet に契約をデプロイする準備が整いました。
Aleph Zero テストネットへの契約のデプロイ
このチュートリアルでは、Aleph Zero ブロックチェーン上のスマート コントラクト環境と対話するいくつかの方法について説明します。
ここで、新しいスマート コントラクトを Aleph Zero テストネットにデプロイします。Aleph Zero ブロックチェーン上のスマート コントラクト環境とやり取りする方法は複数あります。ここでは、Contracts UI を使用する方法と、cargo contract
ツール経由でコマンド ラインを使用する方法の 2 つを紹介します。
契約UI
契約の展開
スマート コントラクトの展開と操作に必要なすべてのツールは、Contracts UIとして便利にパッケージ化されています。開発者 Web ウォレットを使用してアカウントを作成し、 Faucetから無料の TZERO を取得していることを確認してください。そうしないと、ウォレットの一部のタブとボタンが表示されない場合があります。
[開発者] タブに移動し、ポップアップ メニューの [コントラクト] をクリックして、スマート コントラクト コントラクト UI にアクセスします (上記のリンクに直接アクセスすることもできます)。
Contracts UI に入ったら、サイド メニューの [新しい契約を追加] をクリックしてデプロイメント ページに移動し、[新しい契約をアップロード] を選択します。
契約を展開するために使用するアカウントを選択します (複数ある場合)。このアカウントは、mytoken
契約によって作成された新しいトークンの初期供給全体を保持します。次に、下の [契約バンドルのアップロード] フィールドをクリックし、mytoken.contract
以前に生成したファイルの場所を選択しますcargo contract
(フォルダー内にあるはずですmytoken/target/ink/
)。すべてが正常であれば、[有効な契約バンドルです] というテキストが表示されます。
「次へ」をクリックします。インスタンス化するために、コントラクトのコンストラクタにパラメータを指定するよう求められます。この場合、これはトークンの初期供給量にすぎません (ここでは任意の数を選択できます。アカウントの TZERO 残高とはまったく関係ありません)。
いくつかのカスタム オプションがありますが、これについては後のチュートリアルで説明します。右側のコスト見積もりに注目してください。この見積もりでは、とりわけ、アカウントにこの契約を作成するのに十分な残高があるかどうか (つまり、ガス料金をカバーできるかどうか) がわかります。
すべてがうまくいけば、次の画面が表示されます。
残っているのは、「アップロードしてインスタンス化」ボタンをクリックして契約をデプロイすることだけです。選択したアカウント マネージャーを使用してトランザクションに署名する必要があります (現在のデフォルトは Polkadot.js 拡張機能です)。その後、契約に関する情報と、契約を呼び出すメソッドを選択するためのドロップダウン リストを含む画面が表示されます。
「メタデータ」タブを選択して、コントラクトで呼び出し可能なメソッドを表示することもできます。
契約とのやり取り
いよいよ、新しいトークンを試してみましょう。左側の契約リストから「mytoken」を選択した場合、契約で呼び出すメソッドを選択するためのドロップダウンが表示されます。
読み取り専用メソッドはbalanceOf
、totalSupply
右側の「結果」モーダルに結果をすぐに返すことがわかります。これは、読み取り専用であるため、呼び出しのトランザクションを作成する必要がないためです。
興味深いのはtransfer
メソッドを呼び出す部分です。
送金の有効な受取人を設定するには、2 番目のアカウントが必要になります (実際には、アカウント アドレスの形式が正しい限り、既存のアカウントに関連付ける必要はありません。ただし、テスト目的で有効なアドレスを取得するには、別のアカウントを作成するのが最も簡単な方法です)。
転送される金額を入力する必要があります (契約の作成時に選択した初期供給量よりも大きい値を入力した場合に何が起こるかを試すことができます)。ここでも、追加オプションはデフォルト値のままにしておきます。
契約のインスタンス化と同様に、画面の右側に便利なガス見積もりがあり、これを使用して、この呼び出しを実行するのに十分な資金があるかどうかを確認できます (ガス料金に関して)。もう一度トランザクションに署名すると、転送が完了します。 を使用してbalanceOf
、転送が実際に行われたかどうかを確認できるようになりました。
コマンドライン
契約の展開
Aleph Zero ブロックチェーン上のスマート コントラクトをより自動化され、プログラム可能な方法で操作したい場合は、cargo contract
コントラクトをコンパイルしたコマンド ライン ツールを使用して、上記のすべてのアクションを実行することもできます。 のすべての外部関連機能の簡単な概要については、こちらをcargo contract
ご覧ください。
ライブ チェーンと対話するすべてのcargo contract
サブコマンドは、チェーンのエンドポイント アドレスとユーザーの秘密鍵 (シード フレーズ) を定義するフラグを使用して呼び出す必要があります。このセクションのコマンドをより簡潔にするために、まずこれらのフラグで使用される値を持つ環境変数をいくつか定義しましょう。
export SEED="[put your 12 words seed phrase here]"
export URL="wss://ws.test.azero.dev"
新しいコントラクトのデプロイはinstantiate
サブコマンドで実行できます。コントラクトが存在するフォルダーにいることを確認しmytoken
、次のコマンドを実行します。
cargo contract instantiate --suri "$SEED" --url "$URL" \
--constructor new_token \
--args 1000
このコマンドの出力には、デプロイメント トランザクションの結果としてチェーンによって生成されたさまざまなイベント (料金の支払い、連絡先のアカウントの作成など) のリストが含まれます。最後のイベントはSystem ➜ ExtrinsicSuccess
デプロイメントが成功したことを示し、その後に作成したコントラクトのアドレスに関する情報が続きます。コントラクトとのやり取りをより便利にするために、このアドレスを別の環境変数に保存しましょう。
export CONTRACT="5GNruCfnGXjSPkW7LkRnB45MiHJJtvc6NBKZnDSnFh4So3ws
契約とのやり取り
ウェブ ウォレットのセクションで前述したように、スマート コントラクトで実行できる呼び出しには 2 つの種類があります。コントラクトの状態を変更せずに問い合わせる状態クエリと、状態を変更し、署名済みトランザクションの送信と手数料の支払いを要求する実行可能呼び出しです。これら 2 種類のアクションは、フラグcargo contract
によって区別されます--dry-run
。
まず、最も単純な引数なしの状態クエリを実行して、トークンの総供給量を調べてみましょう。コピー
cargo contract call --suri "$SEED" --url "$URL" \
--contract "$CONTRACT" \
--message total_supply \
--dry-run
出力には、関数によって返されたデータなどが含まれますtotal_supply
。コピー
Result Success!
Reverted false
Data 1000
Gas Consumed 248300975
Gas Required 6815744000
Storage Deposit StorageDeposit::Charge(0)
のような引数を使用して状態クエリを実行するには、連絡先とをデプロイしてそのコンストラクターを呼び出したときと同様に、フラグをbalance_of
追加する必要があります。--args
cargo contract call --suri "$SEED" --url "$URL" \
--contract "$CONTRACT" \
--message balance_of \
--args 5FWmHxBXH4WfrryA6xdbaQRJALJ549aL11HMyybqDy5iNRtE \
--dry-run
Output:
Result Success!
Reverted false
Data 1000
Gas Consumed 322051074
Gas Required 6815744000
Storage Deposit StorageDeposit::Charge(0)
ここでの引数は、任意の有効なアカウント アドレスになります。もちろん、この時点では、コントラクト作成者 ( に入力したシード フレーズに関連付けられたアドレス$SEED
) 以外のすべてのアカウントのトークンは 0 で、作成者は合計 1000 トークンの供給量を保有しています。そこで、トークンの一部を別のアカウントに転送して変更してみましょう。コピー
cargo contract call --suri "$SEED" --url "$URL" \
--contract "$CONTRACT" \
--message transfer \
--args 5D853t8wQuHJpfWvtcB3VUyKo8Ki44HQwgTmynGT4i5UVhbr 100
今回はチェーンの状態を変更するトランザクションを送信したいので、--dry-run
フラグは省略する必要があります。出力には、呼び出しが成功したことを示す familiar で終わるトランザクションによって生成されたイベントのリストが含まれますSystem ➜ ExtrinsicSuccess
。これで、100 トークンの転送が実際に行われたことを確認できます。
cargo contract call --suri "$SEED" --url "$URL" \
--contract "$CONTRACT" \
--message balance_of \
--args 5FWmHxBXH4WfrryA6xdbaQRJALJ549aL11HMyybqDy5iNRtE \
--dry-run
Output:
Result Success!
Reverted false
Data 900
Gas Consumed 322051074
Gas Required 6815744000
Storage Deposit StorageDeposit::Charge(0)
コピー
cargo contract call --suri "$SEED" --url "$URL" \
--contract "$CONTRACT" \
--message balance_of \
--args 5D853t8wQuHJpfWvtcB3VUyKo8Ki44HQwgTmynGT4i5UVhbr \
--dry-run
Output:
Result Success!
Reverted false
Data 100
Gas Consumed 322051074
Gas Required 6815744000
Storage Deposit StorageDeposit::Charge(0)
次のステップ
おめでとうございます。これで、スマート コントラクト開発者になりました。ink! スマート コントラクトについてさらに詳しく知りたい場合は、優れたink! ドキュメント を詳しく読むことをお勧めします。
また、ここにある ink! コントラクトの例のコレクションを確認することもできます。問題や質問がある場合は、いつでも喜んでお手伝いいたします。alephzero.org に記載されているチャネルのいずれかを使用してお問い合わせください。
監査および研究論文
Aleph Zero の安全なスマート コントラクト、zk 対応ブロックチェーン、プライバシー強化テクノロジーの詳細については、当社のホワイト ペーパーをご覧ください。
この記事は以下サイトの機械翻訳です。