多くの場合、スマート コントラクトの書き方を学び始めると、最初に耳にするのは Solidity と Ethereum です。私も最初に耳にしたのはこれです。ほとんどのチュートリアルではこれらに焦点を当てていますが、それには十分な理由があります。Solidity により、ブロックチェーン上で動作するプログラムの作成が可能になり、Ethereum は多くの人が始める場所になりました。
しかし、Solidity は唯一のスマート コントラクト言語ではありません。また、分散型アプリケーションをサポートするブロックチェーンは Ethereum だけではありません。
また、 The Open Networkの略称であるTONもあります。これは Telegram によって作成されましたが、現在はパブリックのコミュニティ主導のチェーンになっています。高速で軽量で、Ethereum で慣れ親しんでいるものとは少し異なる方法で処理します。これには、スマート コントラクトの記述方法も含まれます。TON のドキュメントを調べ始めたとき、スマート コントラクトを記述するための 4 つの異なる言語、 Tact、Tolk、FunC、および Fiftに出会いました。ここでは 4 つすべてについて詳しく説明しません。
このガイドでは、Tact 言語に焦点を当て、ユーザーが投票し、チェーン上で結果を確認できる基本的な投票契約を Tact 言語を使用して構築する方法を説明します。
私が最初にタクトを学ぶことにした理由
TON エコシステムは実際には複数の言語をサポートしており、それぞれが異なるユースケース、抽象化レベル、開発者エクスペリエンスを提供します。以下に、それぞれの概要を示します。
- FunC は、TON スマート コントラクトを記述するための従来の言語です。低レベルで、コントラクトの内部動作を正確に制御できます。強力ですが、スタック操作、メモリ レイアウト、決定論的実行などの概念を含む、TON 仮想マシン (TVM) の動作を理解する必要もあります。構文は C に少し似ていますが、以前にそのスタイルの言語を使用したことがない場合は、なじみがないと感じるかもしれません。
- Fiftは通常 FunC と一緒に使用されます。これはスタックベースの言語で、主に TVM と直接やり取りするために使用され、デプロイ、デバッグ、オンチェーン計算の実行に使用されます。通常、完全なスマート コントラクトを作成するために最初に使用する言語ではありませんが、TON の全体的な開発ワークフローでは重要です。
- Tolk は、まだ進化を続けている新しい追加機能です。私が収集した情報によると、ツールと高水準言語との互換性を向上させることを目的としています。期待は持てますが、まだ広く採用されておらず、文書化もされていません。
- Tact は、TON スマート コントラクト開発をよりアクセスしやすく、開発者にとって使いやすいものにするために特別に設計された高水準言語です。Tact は、低レベルの複雑さを大幅に簡素化し、ロジックをわかりやすく読みやすい方法で記述することに集中できるようにします。構文は TypeScript や Solidity で見られるものに近いため、TVM の内部を深く調べる必要がなく、はるかに簡単に始めることができます。
Tact は、TON ブロックチェーン上で契約を構築および展開するためのより迅速なパスを提供します。
タクトの仕組みを理解する
コードを書き始める前に、Tact スマート コントラクトの構造を理解することが重要です。一般的な Tact コントラクトには、いくつかのコア コンポーネントが含まれています。
contract
ブロック – ここでコントラクトの名前を定義し、状態変数を宣言します。init
ブロック – コントラクトの状態変数を初期化し、コントラクトの開始条件を設定します。このブロックは、デプロイメント時に 1 回実行されます。receive
ブロック – イベント リスナーのようなものです。受信メッセージを処理し、コントラクトがそれにどのように反応するかを定義します。ゲッター関数 (
get fun
) – これらはオプションの読み取り専用関数であり、ユーザーまたは他のコントラクトがコントラクトの状態を変更せずに照会できるようにします。
Tact はメッセージベースの通信を使用します。これは、TON 上のすべてのやり取りの仕組みです。各コントラクトはメッセージを受信し、独自のreceive
ブロックで処理します。このメッセージベースの構造により、コントラクト ロジックをモジュール式で保守しやすい方法で整理できます。
それでは、簡単な投票契約を構築して、これを実際の例に適用してみましょう。
Tact を使用した最初の投票契約の構築 (TON Web IDE を使用)
このセクションでは、Tact を使用して基本的な投票システムを実装する方法について説明します。この投票コントラクトにより、ユーザーは事前に定義された候補者に投票でき、各候補者が受け取った投票の合計数を追跡できます。
私たちは、ローカルに何もインストールせずに契約を記述、構築、テストできるブラウザ内ツールである TON Web IDE 内ですべてを実行します。
ステップ1 – TON Web IDEを開く
- https://ide.ton.orgにアクセスしてください。
- 「新しいプロジェクトを作成」をクリックします。ポップアップで次の操作を行います。
- 言語がTactになっていることを確認してください。
- テンプレートとして「空白の契約書」を選択します。
- プロジェクトに
VotingContract
のような名前を付けます。 - [+ 作成]をクリックします。
ステップ2 – 投票契約コードの作成
プロジェクトを作成したら、 main.tact
ファイルを開きます。定型的な設定が表示されます。
// Import the Deployable trait so the contract can be deployed easily import "@stdlib/deploy"; contract BlankContract with Deployable { init() { } }
-
import "@stdlib/deploy";
デプロイメントを機能させるために必要であり、コードから削除しないでください。 -
BlankContract
はプレースホルダー名です。 -
init()
ブロックは、コントラクトがデプロイされたときに 1 回だけ実行され、状態変数を初期化するために使用されます。
それでは、独自のコードをマッピングしてみましょう。
まず、投票用のメッセージ構造を定義します。
// Import the Deployable trait so the contract can be deployed easily import "@stdlib/deploy"; // Define a message structure for voting message Vote { candidate: Int as uint32; // 1 = Alice, 2 = Bob }
これは投票メッセージです。誰かが投票したいときは、数字を含むメッセージをコントラクトに送信します。
- アリスは1
- ボブは2
Tact はこの構造を使用して、受信した投票を処理し、どの候補者がポイントを獲得するかを決定します。
次に、契約を設定し、各候補者の投票を追跡するための 2 つの状態変数を追加します。
... contract VotingContract with Deployable { // State variables to track votes votesAlice: Int as uint32; votesBob: Int as uint32;
契約内で、2 つの変数を定義しました。
-
votesAlice
: Alice が受け取った投票数を格納します。 -
votesBob
: Bob が受け取った投票数を格納します。
ここで、 init
ブロック内でこれらの投票数をゼロに初期化し、契約が最初にデプロイされたときの開始状態を設定します。
init() { self.votesAlice = 0; self.votesBob = 0; }
init
ブロックは、コントラクトがデプロイされたときに 1 回だけ実行され、両方の投票カウントをゼロに設定します。
ここでロジックが登場します。投票が送信されると、コントラクトで誰に対する投票かを確認し、正しい投票数を増やすようにします。
// Handle vote messages receive(msg: Vote) { if (msg.candidate == 1) { self.votesAlice += 1; } else if (msg.candidate == 2) { self.votesBob += 1; } }
したがって、投票が受け取られると、次のようになります。
-
msg.candidate
が1の場合、votesAlice
に+1を追加します。 -
msg.candidate
が2の場合、votesBob
に+1を追加します。
最後に、コントラクトの状態を変更せずに誰でも各候補者の投票数を照会できるようにするゲッター関数を作成します。
// Getter for Alice's votes get fun getVotesForAlice(): Int { return self.votesAlice; } // Getter for Bob's votes get fun getVotesForBob(): Int { return self.votesBob; } }
これら 2 つのゲッター関数を使用すると、契約内容を変更せずに各候補者が獲得した投票数を確認できます。これは読み取り専用の操作です。
以下は完全な投票契約コードです。
import "@stdlib/deploy"; // Define a message structure for voting message Vote { candidate: Int as uint32; // 1 = Alice, 2 = Bob } contract VotingContract with Deployable { // State variables to track votes votesAlice: Int as uint32; votesBob: Int as uint32; init() { self.votesAlice = 0; self.votesBob = 0; } // Handle vote messages receive(msg: Vote) { if (msg.candidate == 1) { self.votesAlice += 1; } else if (msg.candidate == 2) { self.votesBob += 1; } } // Getter for Alice's votes get fun getVotesForAlice(): Int { return self.votesAlice; } // Getter for Bob's votes get fun getVotesForBob(): Int { return self.votesBob; } }
ステップ4 – 契約の構築と展開
- 左側のサイドバーで、 「ビルドとデプロイ」をクリックします。
- [環境]で、 [サンドボックス]が選択されていることを確認します。
- main.tactが選択されていることを確認し、 [ビルド]をクリックします。これにより、コントラクトがコンパイルされ、コード内の構文エラーや問題がチェックされます。
- 次に、ドロップダウンでVotingContractが選択されていることを確認します。これは、デフォルトのプレースホルダーではなく、実際の契約です。表示されない場合は、 Ctrl + Sを押してファイルを保存し、IDE が更新された契約を検出できるようにします。
- 次に、 「ReDeploy」をクリックします。すべてが正常に機能すると、契約が Sandbox に正常にデプロイされたことを示す確認メッセージがログに表示されます。
ステップ5 – 契約書とやり取りする
デプロイしたら、下にスクロールすると 2 つのセクションが表示されます。
- ゲッター:
getVotesForAlice
、getVotesForBob
- 受信者:
Vote
投票するには:投票セクションで、 candidate
入力フィールドに1
入力し、 [送信] をクリックします。これで Alice に投票できました。これを繰り返してさらに投票することができます。
投票数を確認するには: getVotesForAlice
の下のCallをクリックし、ログパネルで投票数を確認します。
- Bobに対しても同じように、
candidate
フィールドに2
送信し、getVotesForBob
チェックします。
私のテスト実行では、Alice に9 回、Bob に6 回投票しましたが、ゲッター関数はまさにそれを示しました。
💭 最後に: 構築し続け、探索し続けよう
🙌 最後まで読んでくださった方、おめでとうございます!
シンプルな投票コントラクトが Tact でどのように機能するかを確認したので、TON でのスマート コントラクト開発への第一歩を踏み出しました。このコントラクトは基本的なものですが、その構造と概念はより複雑なロジックにも適用されます。
実験を続けたい場合は、この契約を拡張するか、 https://tact-by-example.org/allから他の事前構築済みテンプレートを調べてみてください。TON Web IDE を使用すると、さまざまなユースケースを簡単に試すことができ、構築と学習を迅速化するためのテンプレートも付属しています。
さあ、微調整し、テストし、より良いものを作りましょう。