3. Resource Contract Tutorial

[Previous << 2. Hello World](https://qiita.com/flowcadence/items/8d5bce1f1feaf5404d2b)
[Next >> 4. Capability Tutorial](https://qiita.com/flowcadence/items/87b1cc1ff58417dc086d)

https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a#cadenceの言語仕様を学ぶ

<h1 id="Overview">Overview</h1>

:::note warn
💡 TIP
このチュートリアルのスターターコードを Flow Playground で開きます。
https://play.flow.com/ddf0177e-81c8-4512-ac2e-28036b1a3f89
チュートリアルでは、このコードとやり取りするためにさまざまな操作を行うよう求められます。
:::
:::note info
ACTION
ユーザーにアクションを要求する指示は、常にこの吹き出しボックス内に表示されます。ハイライトされたアクションは、コードを実行するために必要なすべてですが、言語の設計を理解するには、残りの部分を読むことも必要です。
:::
このチュートリアルは、前回の`Hello World`チュートリアルを基にしています。このチュートリアルを開始する前に、次の内容を理解しておく必要があります。
* [Accounts](https://qiita.com/flowcadence/items/5ddbb79fe8438850cf57)
* [Transactions](https://qiita.com/flowcadence/items/0d73ce09c9da04d8b697)
* Signers
* [Field Types](https://qiita.com/flowcadence/items/d15aeb14b6bbddd9e717)

このチュートリアルではアカウントについて理解を深めつつ、[Resource](https://qiita.com/flowcadence/items/f9b95df70c80a90d3a20)を紹介し、これによってアカウントとどうやりとりするのかを習得していきます。

リソースは、Cadenceの最も重要な機能の1つです。

Cadenceでは、リソースは他の言語における構造体やクラスに似た複合型の一つですが、いくつかの特別なルールを持っています。

以下に、リソースの宣言例を示します。
```ruby
access(all) resource Money {

  access(all) let balance: Int

  init() {
    self.balance = 0
  }
}
```
ご覧下さい、リソースは通常の`struct`定義みたいに見えます。その違いは動作内にあります。

Resourceは、アセット及びオブジェクトの*直接所有(direct ownership)*をモデル化したい場合に便利です。*直接所有*により、アクセスを可能にするパスワードや証明書の代わりにあなたの資産を表す*実際のオブジェクト*を所有できることを意味します。他のプログラミング言語の従来の構造体やクラスは、*コピー*が可能であるため、直接所有を表す理想的な方法にはなりません。コーディングエラーによって同じ資産の複数コピーが簡単に作成することが出来ると、資産の価値を持たせるための希少性を台無しにするからです。私たちは、家屋、自動車、数百万ドルの銀行口座、あるいは馬などの規模での損失や盗難を考慮しなければなりません。リソースはこの点で、資産を明示的に作成、破棄、移動させることでこの問題を解決させます。

このチュートリアルでは以下のことを行います。
1. リソースを宣言したスマートコントラクトをデプロイします
2. リソースをアカウントのストレージに保存します
3. トランザクションを使用して作成したリソースに対しやりとりします

<h1 id="Implementing-a-Contract-with-Resources">Implementing a Contract with Resources</h1>

リソースに対してやり取りするには、いくつかの重要な概念を学んでください。
* `create`キーワードの使用
* `<-` 移動演算子
* [アカウントストレージAPI](https://qiita.com/flowcadence/items/129d58ae7cb962056c6c)

まず、`create`キーワードと`<-`移動演算子を使ってどうやってリソースを作成していくかを見ていきましょう。
`create`キーワードを使用してリソースを初期化します。リソースはそれを定義したスマートコントラクトの中でのみ作成できます。

`<-`移動演算子は、リソースを変数に移動させるために使用します。リソースには代入演算子`=`を使用できないため、リソースを初期化したり、新しい変数に代入する時には、`<-`移動演算子を使用する必要があります。これは、リソースが文字通りある場所から別の場所に移動することを意味します。そのリソースを保持していた古い変数または場所は移動後、無効な値になります。これがCadenceがリソースを1場所にしか同時に存在させないことを保証する手段の1つです。

:::note info
ACTION
ファイル名が`HelloWorldResource.cdc`であるアカウント`0x06`タブを開きます。
`HelloWorldResource.cdc`には、以下のコードが含まれているはずです。
:::
```ruby
access(all) contract HelloWorld {

    /* Declare a resource that only includes one function. */
    access(all) resource HelloAsset {

        /* A transaction can call this function to get the "Hello, World!"
           message from the resource. */
        access(all) view fun hello(): String {
            return "Hello, World!"
        }
    }

    /* We're going to use the built-in create function to create a new instance
       of the HelloAsset resource */
    access(all) fun createHelloAsset(): @HelloAsset {
        return <-create HelloAsset()
    }
}
```
:::note info
ACTION
Deployボタンを使用して、このコードをアカウント`0x06`にデプロイします。
:::
まず私達は、`0x06`アカウントに新しい`HelloWorld`コントラクトを宣言します。この`HelloWorld`コントラクトで私たちは以下をしています。
1. `HelloAsset`リソースをパブリックスコープである`access(all)`で宣言します。
2. `hello()`リソース関数を`HelloAsset`の中に、パブリックスコープである`access(all)`で宣言します。
3. `HelloAsset`リソースを`create`する`createHelloAsset()`コントラクト関数を宣言します。
4. `createHelloAsset()`関数はリソースを関数が返すように、移動演算子（`<-`）を使用します。

これは、スマートコントラクトで実行できることの一例です。Cadenceは、デプロイされたスマートコントラクト内で型の定義を宣言できます。(補足: Cadenceでは一つ一つのリソースが一つ一つの型になります。)型の定義は、特定のデータセットがどのように構成されているかを説明するものです。型の定義自体は、そのデータのコピーやインスタンスではありません。他のアカウントはこれらの定義をインポートし、それらの型のオブジェクトとやり取りすることができます。

私達が先ほどデプロイしたこのスマートコントラクトでは、`HelloAsset`リソースの定義とリソースを作成する関数の宣言をしています。

このスマートコントラクトについて、リソース部分から詳しく見ていきましょう。リソースとは、Cadenceがスマートコントラクト設計に導入した最も重要なものの1つです。
```ruby
access(all)
resource HelloAsset {
    access(all)
    view fun hello(): String {
        return "Hello, World!"
    }
}
```
<h1 id="Resources">Resources</h1>

`resource`と、`struct`または`class`の主な違いは、リソースのアクセス範囲です。
* resourceの各インスタンスは、厳密に1つの場所にのみ存在することができ、コピーすることはできません。ここでいう場所とは、アカウントストレージ、関数内の一時変数、スマートコントラクト内のストレージ フィールドなどを指します。
* resourceは、アクセスされると、明示的に1つの場所から別の場所に移動されなければなりません。
* また、resourceは関数実行の終了時にスコープ外に出ることもできません。明示的にどこかに保存するか、明示的に破棄しなければなりません。

これらの特性により、コーディングのミスからリソースを誤って失うことが不可能になります。

**resourceは、resourceが定義されたスコープ(補足: スマートコントラクト)内でのみ作成できます。**

これにより、他のユーザーが定義したリソースオブジェクトを、誰でも任意の数だけ作成できることを防止できます。

<h1 id="The Move Operator (<-)">The Move Operator (<-)</h1>

今回の例では、`HelloAsset`リソースを作成できる関数を宣言しました。
```ruby
access(all)
fun createHelloAsset(): @HelloAsset {
    return <-create HelloAsset()
}
```
`@`シンボルは、それがスマートコントラクト内で定義した`HelloAsset`型の**リソース**であることを指し示しています。この関数では、`HelloAsset`型のリソースを作成しそれを返すために、移動演算子を使用しています。新しいリソースオブジェクトを作成するためには、`create`キーワードを使用します。

ここで、`<-`記号を使用しています。[これは移動演算子です](https://cadence-lang.org/docs/language/operators#move-operator--)。`<-`移動演算子は、リソースにおける代入の代入演算子`=`を置き換えます。リソースの代入である、と明示する必要があるため、以下の処理を行う時には`<-`移動演算子を使用する必要があります。
* リソースを定数または変数の初期値とする時
* リソースが代入で別の変数に移動する時
* リソースが引数として関数に移動する時
* リソースが関数から返される時

リソースが移動すると、古い場所は無効となり、リソースオブジェクトは新しい場所のコンテキストに移動します。

例えば、変数`first_resource`にリソースがあるとすると:
```ruby
/* Note the `@` symbol to specify that it is a resource */
var first_resource: @AnyResource <- create AnyResource()
```
そして、それを`second_resource`という新しい変数に代入したいとします。代入を行った後、`first_resource`は無効となります。これは、リソースが新しい変数に移動したためです。
```ruby
var second_resource <- first_resource
/* first_resource is now invalid. Nothing can be done with it */
```
リソースを通常の代入することは許可されていません。通常の代入は値をコピーするだけだからです。リソースは同時に1つの場所にしか存在できないため、移動は移動演算子`<-`を使用してコード内で明示して示される必要があります。

<h1 id="Create-Hello-Transaction">Create Hello Transaction</h1>

では次に、`createHelloAsset()`関数を実行し、`HelloAsset`リソースをアカウントのストレージに保存するトランザクション処理を行います。

:::note info
ACTION
`Create Hello`という名前のトランザクションを開きます。
`Create Hello`には以下のコードを含めます。
:::

```ruby
/* create_hello.cdc
   This transaction calls the createHelloAsset() function from the contract
   to create a resource, then saves the resource
   in the signer's account storage using the "save" method. */
import HelloWorld from 0x06

transaction {

    /* `auth(SaveValue) &Account` signifies an account object
        that has the `SaveValue` authorization entitlement, which means
        that this transaction can't do anything with the &Account object
        besides saving values to storage.
        You will learn more about entitlements later */
	prepare(acct: auth(SaveValue) &Account) {
        /* Here we create a resource and move it to the variable newHello,
           then we save it in the signer's account storage */
        let newHello <- HelloWorld.createHelloAsset()

        acct.storage.save(<-newHello, to: /storage/HelloAssetTutorial)
  }

    /* In execute, we log a string to confirm that the transaction executed successfully. */
	execute {
        log("Saved Hello Resource to account.")
	}
}
```
このトランザクションの処理は以下の通りです。
1. `HelloWorld`の定義をアカウント `0x06` からインポートします。
2. `createHelloAsset()` 関数を使用してリソースを作成し、それを `newHello` に移動します。
3. 作成したリソースを、トランザクションに署名したアカウントのストレージ（ `/storage/HelloAssetTutorial`のパス）に`save`します。
4. 「`Saved Hello Resource to account.`」というテキストをコンソールにログ出力します。

これは、`prepare`フェーズを使用した最初のトランザクションです。`prepare`フェーズとは、[アカウント参照（&Account）](https://qiita.com/flowcadence/items/5ddbb79fe8438850cf57)を介して署名をしたアカウントにアクセスが出来る、唯一の場所です。アカウント参照は、アカウントとのやり取りに使用出来るさまざまなメソッドにアクセスすることが出来ます。一例として、アカウントのストレージがあります。上記の例では、トランザクションは `auth(SaveValue) &Account` というものを使用しており、これは`SaveValue`という認証権限(authorization entitlement)を意味しています。このトランザクションは、`&Account`アカウント参照オブジェクトに対して、アカウントのストレージに値を保存することは出来るけど、それ以外の操作はできないということを意味しています。権限(Entitlement)については、後のチュートリアルで詳しく説明します。詳細については、権限に関するドキュメント([the entitlements documentation](https://qiita.com/flowcadence/items/572df270135946f5290e#entitlements))を参照してください。

また、全アカウント権限(Entitlement)に関する可能な限りのドキュメントを、言語リファレンスの[Accountセクション](https://qiita.com/flowcadence/items/5ddbb79fe8438850cf57#performing-write-operations)で見ることが出来ます。このチュートリアルでは、アカウントストレージの`/storage/`への保存やそこからロードを行うアカウントの関数を使用していきます。

アカウントはオブジェクトをパス([paths](https://qiita.com/flowcadence/items/9767ec3f9b8d757d75bf))に保存します。パスは基本的にアカウントのファイルシステムを表し、ユーザー定義のパスを使って、どこにでもオブジェクトを保存することができます。多くの場合、スマートコントラクトはそのスマートコントラクトのオブジェクトをどこに保存されるかをユーザーに明示しています。これによって、コードは標準的な方法でこれらのオブジェクトにアクセスする方法を知ることが出来ます。

executeフェーズにおけるアカウントストレージへのアクセスを禁止していること、および権限(Entitlement)の使用によって、任意のトランザクションが署名者アカウントのどのアセットや領域/パス(areas/path)を変更できるかを静的に検証可能にします。 トランザクションの送信を行うブラウザウォレットやアプリケーションは、これを使用して、トランザクションが変更するであろう内容をユーザーに表示することができます。これにより、ウォレットがユーザーの実行するトランザクションに関する情報をユーザーに提供し、アプリケーションやウォレットから悪意のある危険なトランザクションが送信されることはないという確信を与えることができます。

トランザクションについて、もう少し詳しく見ていきましょう。`HelloAsset`リソースを作成するために、スマートコントラクトの`createHelloAsset()`関数にアクセスし、それによって作成されたリソースを`newHello`変数に移動させます。
```ruby
let newHello <- HelloWorld.createHelloAsset()
```
次に、リソースをアカウントストレージに保存します。Flowでアカウントストレージとやり取りするには、アカウントストレージAPIを使用します。リソースを保存するには、アカウントストレージAPIの[save()](https://qiita.com/flowcadence/items/129d58ae7cb962056c6c)メソッドを使用して、アカウントの`/storage/HelloAssetTutorial`パスにリソースを保存します。
```ruby
acct.storage.save(<-newHello, to: /storage/HelloAssetTutorial)
```
`save`に対する最初のパラメータは、保存されるオブジェクトであり、`to`パラメータはオブジェクトが保存されるパスです。パスはstorageパスでなければならず、`to`パラメータではドメインは`/storage/`のみが許可されます。

指定したパスにすでにオブジェクトが保存されている場合、プログラムは中止(abort)します。Cadenceの型システムにより、リソースが誤って失われることは決してないことを覚えておいてください。リソースをフィールド、配列、ディクショナリ、またはストレージに移動する場合、その場所にすでにリソースが含まれている可能性があります。Cadenceでは、既存のリソースを処理するように開発者を強制し、上書きによって誤って失われることがないようにしています。

また、あなたが識別子としてパス名をチョイスする時、プロジェクトに固有であるものを選ぶことが非常に重要です。現在、アカウントの保存パスはグローバルであるため、プロジェクトが同じ保存パスを使用する可能性があり、**パスが競合する**可能性があります。これは厄介な問題となる可能性があるため、このような問題を避けるために固有のパス名を選択してください。(補足: Cadenceではリソース宣言自体が一つの型であるため型自体は重複しないと考えられる)

最後に、executeフェーズでは、`"Saved Hello Resource to account."`という文言をコンソールにログ出力します。
```ruby
log("Saved Hello Resource to account.")
```

:::note info
ACTION
`0x06`アカウントを唯一の署名者として選択します。`Send`ボタンをクリックして、トランザクションを送信します。
:::
以下のような表示がされるはずです。
```
"Saved Hello Resource to account."
```

:::note info
ACTION
`newHello` をストレージに保存(save)するコード行の削除を試してもいいです。
`newHello` のエラーが表示されるはずです。そのエラーには「`loss of resource`」と表示されます。これは、リソースが適切に扱われていないことを意味します。プログラムでこのエラーが表示された場合、明示的に保存または破棄されていないリソースがどこかにあることを意味し、プログラムが不正であることを意味します。
トランザクションのチェックが適切になるようにするために、コード行を再追加します。
:::
この場合、選択したアカウントで何かを保存するのは初めてなので、ストレージの`/storage/HelloAssetTutorial`の場所は空であることが分かります。実際のアプリケーションでは、誤って上書きをしようとしてトランザクションを中止しないように、保存する場所のパスで、必要なチェックとアクションを実行するでしょう。

トランザクションを実行したので、アカウント`0x06`のストレージには新たに作成された`HelloWorld.HelloAsset`リソースが格納されているはずです。これを確認するには、左下のアカウント`0x06`をクリックします。これにより、アカウント内のさまざまなコントラクトとオブジェクトのビューが開きます。`HelloWorld`コントラクトと`HelloAsset`リソースのエントリが表示されるはずです。
```ruby
Deployed Contracts:
[
  {
    "contract": "HelloWorld",
    "height": 6
  }
]
Account Storage:
{
    "Private": null,
    "Public": {},
    "Storage": {
        "HelloAssetTutorial": {
            "Fields": [
                39
            ],
            "ResourceType": {
                "Fields": [
                    {
                        "Identifier": "uuid",
                        "Type": {}
                    }
                ],
                "Initializers": null,
                "Location": {
                    "Address": "0x0000000000000005",
                    "Name": "HelloWorld",
                    "Type": "AddressLocation"
                },
                "QualifiedIdentifier": "HelloWorld.HelloAsset"
            }
        }
    }
}
```
`FlowToken`オブジェクトも表示されているのがわかるでしょう。すべてのアカウントは、FlowTokenアセットを使用する能力が自動的に初期化されています(補足: FlowTokenはトランザクションフィーに必要なので全てのアカウントは初期化時にこれを保持します)。現時点では、それらについて心配する必要はありません。

<h1 id="Load-Hello-Transaction">Load Hello Transaction</h1>

次に、トランザクションで`HelloAsset`リソースの`hello()`メソッドを実行します。

:::note info
ACTION
`Load Hello`という名前がついたトランザクションを開きます。
`Load Hello`には、以下のコードが含まれているはずです。
:::
```ruby
import HelloWorld from 0x06

/* This transaction calls the "hello" method on the HelloAsset object
   that is stored in the account's storage by removing that object
   from storage, calling the method, and then saving it back to the same storage path */

transaction {

    /* In this prepare block, we have to load a value from storage
       in addition to saving it, so we also need the `LoadValue` entitlement
       which additionally allows loading values from storage */
    prepare(acct: auth(LoadValue, SaveValue) &Account) {

        /* Load the resource from storage, specifying the type to load it as
           and the path where it is stored */
        let helloResource <- acct.storage.load<@HelloWorld.HelloAsset>(from: /storage/HelloAssetTutorial)
            ?? panic("The signer does not have the HelloAsset resource stored at /storage/HelloAssetTutorial. Run the `Create Hello` Transaction again to store the resource")

        /* log the hello world message */
        log(helloResource.hello())

        /* Put the resource back in storage at the same spot */
        acct.storage.save(<-helloResource, to: /storage/HelloAssetTutorial)
    }
}
```
このトランザクションは以下の処理を行います。
1. `HelloWorld`定義を`0x06`アカウントからインポートします。
2. `HelloAsset`オブジェクトを移動演算子と[アカウントストレージAPI](https://qiita.com/flowcadence/items/129d58ae7cb962056c6c)の`load`関数を用いて、ストレージから`helloResource`に移動します。
3. `helloResource`に保存された`HelloAsset`リソースの`hello()`関数を呼び出し、結果をログに記録します。
4. リソースを、私たちが移動させる前にあったアカウントのパス`/storage/HelloAssetTutorial`に保存(save)し直します

私達は`prepare`フェーズを再び使用し、渡される[アカウントの参照](https://qiita.com/flowcadence/items/5ddbb79fe8438850cf57)を使ってリソースをloadします。

トランザクションについて、さらに詳しく見ていきましょう。

`HelloAsset`リソースをストレージからロードします。

ストレージからオブジェクトを取り除くには、[アカウントストレージAPI](https://qiita.com/flowcadence/items/129d58ae7cb962056c6c)の`load`メソッドを使用します。
```ruby
let helloResource <- acct.storage.load<@HelloWorld.HelloAsset>(from: /storage/HelloAssetTutorial)
```
指定した型のオブジェクトがパスに存在する場合は、この関数はそのオブジェクトを返します。そして、アカウントストレージには、指定されたパス以下のオブジェクトは含まれなくなります。

ロードするオブジェクトの型の、型パラメータは`<>` に含まれています。 ここで、私達は基本的に`@HelloWorld.HelloAsset`のリソースオブジェクトをこのパスからロードするということを述べています。 パラメータにある型の引数は明示的に指定する必要があります。 (リソースであることを意味する`@`記号に注目してください)

`from`パスはストレージパスでなければなりません。そのため、`/storage/`ドメインのみが許可されます。

指定した型のオブジェクトが指定したパスに存在しない場合、この関数は何も返さない、すなわち`nil`を返します。これは[オプショナル型](https://qiita.com/flowcadence/items/c917af1e35cd46cf6a7f#optionals)といい、

オプショナル型とは、値の存在または非存在を表すことができる値です。オプショナル型には2つのケースがあります。指定した型の値があるか、または何も存在しない（`nil`）かのどちらかです。オプショナル型は、`?`接尾辞を用いて宣言します。
```ruby
let newResource: HelloAsset?  /* could either have a value of type `HelloAsset`
                                 or it could have a value of `nil`, which represents nothing */
```
オプショナル型により、開発者は`nil`の場合をより適切に処理することができるようになります。ここで私達は、`load`で取得した`helloResource`オブジェクトが`nil`である可能性をはっきりと考慮する必要があります（なぜなら、`load`はロードするものがない場合は`nil`を返すからです）。

[nil 結合演算子 (`??`) ](https://qiita.com/flowcadence/items/8e3287f9a4cd9b822065#nil-coalescing-operator)を使用して、オプショナルを「unwrap」します。これは基本的に私達は、`load`メソッドが`nil`を返した場合の対応を処理することを意味します。もし`nil`が返ってきた時は、`??`の後のコードブロックが実行されます。 ここでは、`panic`を実行していまます。これはエラーメッセージとともにトランザクションの実行を中断します。

オプショナル型の詳細と使用方法については、「[Optionals In Cadence](https://qiita.com/flowcadence/items/c917af1e35cd46cf6a7f#optionals)」を参照してください。

コード内でもし何か問題が生じた時に、常にその詳細なエラーメッセージを開発者に提供することは、ユーザーや開発者にとって何が修正されるべきかを明白にする上で**極めて重要**です。

エラーメッセージには、可能であれば以下の内容を含めるべきです。
* スマートコントラクトから由来した場合は、コントラクト名と関数名
* 起きているリテラル エラー(the literal error)の説明
* エラーの原因となっている可能性がある理由の高レベルな説明
* エラーに直結している可能性があるメタデータまたは変数値
* 可能ならば修正方法の提案

私たちのエラーメッセージを見てもらえば分かるとおり、私たちは問題点を正確に説明しています。つまり、リソースがしかるべき保存パスに保存されていないことを説明しています。そして、エラーを修正するための解決策を提案しています。それは、「Create Hello」トランザクションを実行してリソースを保存することです。

Flow NFTのGitHubリポジトリの[スマートコントラクト](https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc#L115-L121)や[トランザクション](https://github.com/onflow/flow-nft/blob/master/transactions/generic_transfer_with_address_and_type.cdc#L46-L50)のエラーメッセージを参考に、詳細かつヘルプフルなエラーメッセージの例をチェックしてみてください。

**`hello()`関数を呼び出す**

次に、`hello()`関数を呼び出し、出力をログに出します。
```ruby
log(helloResource.hello())
```
**リソースを署名者のアカウントに再保存する**

次に私達は、`save`を再び使用して、オブジェクトを元のストレージの場所に戻します。
```ruby
acct.storage.save(<-helloResource, to: /storage/HelloAssetTutorial)
```

:::note info
ACTION
`0x06`アカウントを唯一の署名者として選択します。`Send`ボタンをクリックして、トランザクションを送信します。
:::
以下のような表示がされるはずです。
```
"Hello, World!"
```

<h1 id="Reviewing-the-Resource-Contract">Reviewing the Resource Contract</h1>

このチュートリアルでは、アカウントストレージAPIを使用してトランザクションでリソースとのやり取りを行いながら、Cadenceのリソースの紹介を行いました。

あなたはすべてのスコープからアクセス可能なスマートコントラクトを実装しました。スマートコントラクトには`hello()`という「`Hello, World!`」文字列を返す関数が実装されたリソースが宣言されてあり、また、リソースを作成できる関数を宣言しました。

次に、あなたはこのコントラクトをアカウントにデプロイし、スマートコントラクトの中でリソースを生成するトランザクションを作成し、そのリソースをトランザクションの署名者としていた`0x06`アカウントの中に保存しました。

最後に、トランザクションを使用して`HelloAsset`リソースをアカウントストレージから移動させ、`hello`メソッドを呼び出し、アカウントストレージに再び戻しました。

今ここであなたはこのチュートリアルを完了しましたので、シンプルなCadenceプログラムを書くための以下の基本的知識が身に付きました。
* スマートコントラクトの中にリソースを実装する
* アカウントストレージAPIと`<-`移動演算子を使用して、リソースを保存、移動、そしてロードすること
* トランザクションの`prepare`フェーズを使用して、アカウントストレージからリソースをロードする（取り出す）こと

異なるリソースを作成するためにスマートコントラクトを好きなように変更してください、自由に利用可能な[アカウントストレージAPI](https://qiita.com/flowcadence/items/129d58ae7cb962056c6c)を実験してください、そして自由にあなたのスマートコントラクトの違う関数を実行する新しいトランザクションを作成してください。リソースでできることについてさらに詳しく知りたい場合は、[リソースリファレンスページ](https://qiita.com/flowcadence/items/f9b95df70c80a90d3a20)をご覧ください。


翻訳元

https://cadence-lang.org/docs/tutorial/resources

***
<b>[Previous << 2. Hello World](https://qiita.com/flowcadence/items/8d5bce1f1feaf5404d2b)
</b>

[Flow blockchain / Cadence version1.0ドキュメント](https://qiita.com/flowcadence/items/3073d69c6e9895e68b5a) (3. Resource Contract Tutorial)

<b>[Next >> 4. Capability Tutorial](https://qiita.com/flowcadence/items/87b1cc1ff58417dc086d)</b>