このチュートリアルでは、初めてのスマートコントラクトを作成してデプロイしてみましょう!
💡 TIP
このチュートリアルのスターターコードをFlow Playgroundで開きます。
https://play.flow.com/483b2f33-9e71-40aa-924a-2c5f0ead77aa
チュートリアルでは、このコードとやりとりするためにさまざまな操作を行うよう求められます。
ACTION
アクションが必要な指示は、常にこのような吹き出しボックス内に記載されています。ハイライトされたアクションは、コードを実行するために必要なすべてですが、言語の設計を理解するためには、残りの部分も読むことが必要です。
このチュートリアルでは、アカウント、トランザクション、署名者(signer)など、基本的なCadenceの特徴を実装したスマートコントラクトを一例に、順を追って解説します。
「Hello World」スマートコントラクトは、以下を行います:
-
String
型の単一フィールドを持つスマートコントラクトを作成し、初期化します - 「Hello, World!」というフレーズのフィールドを初期化します
- この挨拶言葉を返す関数をコントラクト内に作成します
このスマートコントラクトをアカウントにデプロイし、次にトランザクションを使ってスマートコントラクトとやり取りを行い、最後にトランザクションにおける署名者の役割について解説します。
How to Use Playground
このチュートリアルでは、Flow Playground という、テスト環境でスマートコントラクトを記述および実行できるインタラクティブなウェブインターフェースを使用します。 また、作成したスマートコントラクトを共同でテストできるよう、作成したスマートコントラクトを保存して他のユーザーと共有することもできます。
Flow Playgroundでアカウントを使用する際には、変更や再設定が可能な5つのデフォルトアカウントから開始します。各アカウントには固有のアドレスがあり、左下のツールバーでアカウントを選択すると、そのアカウントに保存されたスマートコントラクトが開きます。HelloWorld
スマートコントラクトは、他にスマートコントラクトが保存された既存のプレイグラウンドプロジェクトを読み込まない限り、各アカウントにデフォルトで読み込まれています。
このチュートリアルでは、一番上の0x06
アカウントのみを使用します。
Implementing Hello World
まず、「Hello World!
」を返すパブリック関数を含むスマートコントラクトを使うことから始めます。
他のほとんどのブロックチェーンと同様に、Flowのプログラミングモデルはアカウントとトランザクションを中心に構成されています。恒久的に維持されるすべてのステート(状態)はアカウントに保存され、すべてのアカウントは(ユーザー、スマートコントラクト、データストレージ)という同じコア機能を備えています。これは、Ethereumのような他のブロックチェーンとは異なり、Ethereumではアカウントには2つのタイプ(スマートコントラクトアカウントとユーザーアカウント)があります。
このステートへのインターフェース(ステートとやり取りする方法、またはメソッドや関数として知られている)(補足: アカウントストレージAPIのこと。つまりAPIが各アカウントのストレージに用意されている)もアカウントに保存されます。すべての永続的なステートとのやり取りのためのコード実行は、外部ユーザーによって承認されることで、送信されたコードブロックを含むトランザクション内で行われます。
スマートコントラクトは、Flowのアカウントのcontractエリアに存在するコード(その関数)とデータ(そのState)の集合です。各アカウントは、ゼロまたは複数のスマートコントラクトおよびコントラクトインターフェースを持つことができます。contractは、アカウントの所有者が自由に追加、削除、更新(一部制限あり)することができます。それでは、このチュートリアルで使用するHelloWorld
スマートコントラクトを見てみましょう。
ⓘ ACTION
まだ行っていない場合は、このリンクをクリックして、Hello World スマートコントラクト、トランザクション、スクリプトが事前に読み込まれたプレイグラウンド(Playground)を開いてください。
https://play.flow.com/483b2f33-9e71-40aa-924a-2c5f0ead77aa
ⓘ ACTION
Contract 1のスペースに、HelloWorld.cdc
というファイルがあるアカウントの0x06
タブを開きます。
HelloWorld.cdc
には次のコードが含まれているはずです。
// HelloWorld.cdc
//
access(all) contract HelloWorld {
// Declare a public (access(all)) field of type String.
//
// All fields must be initialized in the initializer.
access(all) let greeting: String
// The initializer is required if the contract contains any fields.
init() {
self.greeting = "Hello, World!"
}
// Public function that returns our friendly greeting!
access(all) view fun hello(): String {
return self.greeting
}
}
行access(all) contract HelloWorld
は、すべてのスコープ(access(all)
、特にpublicとして知られている)でアクセス可能なスマートコントラクトを宣言しています。 access(all) let greeting: String
は、すべてのスコープ(access(all
)でアクセス可能なString
型の定数(let
)を宣言しています。
変数を宣言するにはvar
を使用します。これは、let
の場合のように値が一定ではなく、後でスマートコントラクト内のコードによって変更できることを意味します。
これらは両方とも、このインターフェイスはすべてのスコープからアクセスできるが、すべてのスコープから書き込みはできない(補足: 定数だから)ことを意味するアクセス制御仕様の例です。Cadenceで許可されているさまざまなレベルのアクセス制御の詳細については、言語リファレンスのAccess Controlセクションを参照してください。
init()
セクションはイニシャライザーと呼ばれます。これは、スマートコントラクトが最初に作成されたときにのみ実行される特別な関数です。コントラクトに似たオブジェクト、例えば、structやリソースのような他の複合型では、イニシャライザー(init関数)によって宣言されたすべてのフィールドを初期化する必要があります。上記の例では、イニシャライザー(init関数)はスマートコントラクトが初期化されたときにgreeting
フィールドを「Hello, World!
」に設定しています。
HelloWorld
スマートコントラクトの最後の部分は、hello()
と呼ばれるパブリック関数です。この宣言は、String
型の値を返します。 このスマートコントラクトをトランザクションまたはスクリプトにインポートした人なら誰でも、publicフィールドを読み取ったり、publicの型を何かに利用したり、パブリックスマートコントラクト関数を呼び出すことができます。それは、access(all)
または access(all)
が指定されている関数です。
すぐに、このスマートコントラクトを自分のアカウントにデプロイ、その中の関数を呼び出すトランザクションを実行、することになりますが、その前にアカウントとトランザクションとは何かを見てみましょう。
Accounts and Transactions
What is an Account?
各ユーザーには、設定可能なweightを持つ1つ以上の秘密鍵によって管理されるアカウントがあります。つまり、アカウント/ウォレットに対しての複数のコントローラによるサポートは、デフォルトでプロトコルに組み込まれているということです。
アカウントは主に2つの領域に分けられます。
- 最初の領域は、スマートコントラクト領域です。これは、一般的な機能群に関連する型定義、フィールド、および関数を含むスマートコントラクトを格納する領域です。アカウントが格納できるスマートコントラクトの数に制限はありません。ただし、トランザクションがアカウントにデプロイされたコードのコピーを返す(=スマートコントラクトを読み取る)場合を除き、この領域はトランザクションから直接アクセスすることはできません。アカウントの所有者は、そのアカウントにデプロイされたスマートコントラクトを直接追加または更新することができます。
- 2つ目の領域は、アカウントストレージ(account storage)です。この領域は、アカウントが所有するオブジェクトを格納する場所です。これは、Cadenceと他の言語との大事な違いです。他の言語では、アカウントが所有する資産は、常にその資産を定義する中央集中型のスマートコントラクトに格納されます。Cadenceでは、各アカウントは、自身の資産を自身のアカウントストレージにオブジェクトとして直接格納します。アカウントストレージセクションには、これらの格納されたオブジェクトへのアクセスを制御する機能群(Capability)もコードとして格納されます。アカウントストレージと機能群(Capability)については、後のチュートリアルで詳しく説明します。
このチュートリアルでは、私たちのHelloWorld
スマートコントラクトを保存するため、アドレスが0x06
であるアカウントを使用します。
Deploying Code
Cadenceにおける文脈で、アカウントが何であるか理解できたと思いますので、HelloWorld
スマートコントラクトをアカウントにデプロイできるでしょう。
ACTION
アカウント0x06
タブが選択され、HelloWorld.cdc
ファイルがエディタに表示されていることを確認します。デプロイボタンをクリックして、エディタの内容をアカウント0x06
にデプロイします。
出力エリアに、デプロイが成功したことを示すログが表示されているはずです。
Deployed Contract To: 0x06
選択したアカウントのタブにスマートコントラクトの名前が、アカウント番号の下あたりに表示されているでしょう。これは、HelloWorld
スマートコントラクトがアカウントにデプロイされたことを示します。このタブを見ることで、どのスマートコントラクトがどのアカウントにあるかを確認することができます。Flow Playground環境では、各アカウントに任意の数のスマートコントラクトを持つことができます。追加のスマートコントラクトを作成したい場合は、他のスマートコントラクトを開くか、またはプレイグラウンドのコントラクトセクションの横にあるプラス(+)ボタンをクリックします。
Creating a Transaction
Flow Blockchainにおけるトランザクションは、1つ以上のアカウントによって承認された任意のサイズのCadenceコード・ブロックとして定義されます。アカウントがトランザクションを承認すると、そのトランザクション内のコードは承認者のプライベート・ストレージにアクセスできるようになります。アカウントは、アカウントのプライベートキー(private key)を使ってトランザクションに暗号署名を実行することで、トランザクションを承認します。このプライベート・キーは、アカウントの所有者だけがアクセスできる必要があります。承認者の個人資産(private asset)にアクセスできることに加え、トランザクションはスマートコントラクトのパブリック関数を読み込んだり呼び出すことができます。また、他のユーザーのアカウントのパブリック関数にもアクセスできます。このチュートリアルでは、トランザクションを使用して、hello()
関数を呼び出します。
ACTION
Simple Transaction
という名前のトランザクションを開きます。
Simple Transaction
には、次のコードが含まれているはずです。
import HelloWorld from 0x06
transaction {
prepare(acct: &Account) {}
execute {
log(HelloWorld.hello())
}
}
このトランザクションでは、まずアカウント0x06
からHelloWorld
スマートコントラクトをインポートします。もし、アカウントにスマートコントラクトをデプロイしていない場合は、トランザクションはそれに対するアクセスができずインポートは失敗します。この処理により、HelloWorld
から型定義やパブリック関数を含めた、スマートコントラクトコード全体がインポートされることで、トランザクションがそれらを使用してアカウント0x06
のHelloWorld
スマートコントラクトとやり取りすることができます。
他のアカウントからスマートコントラクトをインポートするには、トランザクションの一番上に次の行を入力します。
// Replace {ContractName} with the name of the contract you want to import
// and {Address} with the account you want to import it from
import {ContractName} from {Address}
トランザクションは、大きく分けてprepare
とexecute
の2つのフェーズに分けられます。
-
prepare
フェーズは必須ですが、このチュートリアルでは使用しません。このフェーズについては、後のチュートリアルで説明します。 -
execute
フェーズはトランザクションの本体です。外部のスマートコントラクトやオブジェクトの関数を呼び出したり、トランザクションで初期化されたデータに対して処理を実行することができます。この例では、execute
フェーズでHelloWorld.hello()
を呼び出しています。これにより、HelloWorld
スマートコントラクトのhello()
関数が実行され、その結果(log(HelloWorld.hello())
)がコンソールにログ出力されています。
ACTION
エディタの右下にあるボックスで、トランザクションの署名者(signer)として Account 0x06
を選択します。
Sendボタンをクリックしてトランザクションを送信します
画面下部のトランザクション結果に以下のような内容が表示されるはずです。
Simple Transaction "Hello, World!"
おめでとう、あなたは0x06
のアカウントを署名者(signer)にして、初めてのCadenceトランザクションを実行しました。
このチュートリアルでは、トランザクションに異なる署名者(signer)を使用しても同じ結果が得られますが、後のチュートリアルでは、署名者によって異なる結果が得られる、より複雑な例を利用していきます。
Reviewing HelloWorld
このチュートリアルでは、アカウント、トランザクション、署名者などの用語を含め、Cadence の入門編をカバーしました。すべてのスコープからアクセス可能なスマートコントラクトを実装しました。そのスマートコントラクトにおいて、String
(型)のフィールドが初期化され、値としてHello, World!
が設定され、この値を返す(読み取る)関数を持ちました。次に、このスマートコントラクトをアカウントにデプロイし、スマートコントラクトの関数を呼び出して結果をコンソールにログ出力するトランザクションを実装しました。最後に、アカウント0x06
をこのトランザクションの署名者として使用しました。
チュートリアルを完了したので、簡単なCadenceプログラムを作成するための基本的な知識が身に付き、以下のことが出来るようになりました。
- アカウントに基本的なスマートコントラクトをデプロイする
- トランザクションを使用してスマートコントラクトとやり取りする
- 1人または複数の署名者でトランザクションに署名する
スマートコントラクトを自由に変更して、さまざまな関数を実装したり、利用可能なCadenceの型を試したり、HelloWorld
スマートコントラクトから複数の関数を実行する新しいトランザクションを作成したりできます。
翻訳元->https://cadence-lang.org/docs/tutorial/hello-world