6. Fungible Token Tutorial

[Previous << 5.2 Non-Fungible Token Tutorial Part 2](https://qiita.com/flowcadence/items/0f791b45ca9fd289944a)
[Next >> 7. Marketplace Setup](https://qiita.com/flowcadence/items/20c399a90a9cd9eb5250)

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

このチュートリアルでは、fungible トークンのデプロイ、保存、転送を行っていきます。

:::note warn
💡 TIP
このチュートリアルのスターターコードを Flow Playground で開きます。
https://play.flow.com/65b44962-32c8-49c4-8a69-e96475d5a780
チュートリアルでは、このコードとやり取りするためにさまざまな操作を行うよう求められます。
:::
:::note
ⓘ ACTION
ユーザーにアクションを要求する指示は、常にこのような吹き出しボックス内に記載されています。ハイライトされたアクションは、コードを実行するために必要なこと全てですが、言語の設計を理解するためには、残りの部分を読むことも必要です。
:::
今日、ブロックチェーン上で最も人気のあるスマートコントラクト クラスは、fungible tokens（交換可能なトークン）です。これらのスマートコントラクトは、他のユーザーに譲渡でき、通貨として使用できる同種のトークンを作成します（例えば、イーサリアムのERC-20）。

従来のソフトウェアおよびスマートコントラクトでは、各ユーザーの残高は、ディクショナリのような中央台帳(central ledger)によって追跡されます。

```ruby
/* DO NOT USE THIS CODE FOR YOUR PROJECT */
contract LedgerToken {
    /* Tracks every user's balance */
    access(contract) let balances: {Address: UFix64}

    /* Transfer tokens from one user to the other
       by updating their balances in the central ledger */
    access(all)
    fun transfer(from: Address, to: Address, amount: UFix64) {
        balances[from] = balances[from] - amount
        balances[to] = balances[to] + amount
    }
}
```
Cadenceでは、新しいリソース指向のパラダイムを使用して代替可能なトークンを実装し、中央台帳の使用を避けています。なぜなら、中央台帳を使用することには固有の問題があります。

<h1 id="Flow-Network-Token">Flow Network Token</h1>

Flowでは、ネイティブネットワークトークン（FLOW）は、このチュートリアルで使用されているものと同様のスマートコントラクトを使用して、[通常のfungibleトークンのスマートコントラクト](https://github.com/onflow/flow-core-contracts/blob/master/contracts/FlowToken.cdc)として実装されています。

特別なトランザクションとhooksがあり、トランザクション実行手数料、ストレージ手数料、ステーキングに使用することができますが、それ以外は、開発者やユーザーは、ネットワーク上の他のトークンと同様に扱うことができます。

:::note warn
⚠️ WARNING
このチュートリアルでは、実際に機能するfungibleトークンを実装していますが、教育目的のために簡略化されており、実際のプロジェクトで使用すべきものではないことを覚えておくことが重要です。標準インターフェースと実装例については、[Flow Fungible Tokenスタンダード](https://github.com/onflow/flow-ft)を参照してください。また、fungibleトークンスマートコントラクトの実用版を作成する方法については、[Fungible Token開発者ガイド](https://developers.flow.com/build/guides/fungible-token)を参照してください。
::::
fungible token に慣れていただくために、以下の手順を実行してみましょう。
1. fungible token スマートコントラクトをアカウント` 0x06` にデプロイします。
2. fungible token オブジェクトを作成し、アカウントのストレージに保存します。
3. 他のユーザーがトークンを送信できるように、トークンへの参照(reference)を作成します。
4. 同様の方法で、もう1つのアカウントを設定します。
5. トークンを1つのアカウントから別のアカウントに転送します。
6. スクリプト(Script)を使用して、アカウントの残高を読み取ります。

**このチュートリアルを進める前に**、言語の基本とプレイグラウンド(playground)を学ぶために、[Getting Started](https://qiita.com/flowcadence/items/d74e796356935d409ba4)と[Hello, World!](https://qiita.com/flowcadence/items/8d5bce1f1feaf5404d2b)の手順に従うことをお勧めします。

<h1 id="Fungible-Tokens-on-the-Flow-Emulator">Fungible Tokens on the Flow Emulator</h1>

:::note
ⓘ ACTION
まず、このリンクを開きFungibleトークンスマートコントラクト、トランザクション、スクリプトが事前にロードされたプレイグラウンド(playground)を開きます。
https://play.flow.com/65b44962-32c8-49c4-8a69-e96475d5a780
:::
:::note
ⓘ ACTION
アカウント`0x06`タブを開くと、`BasicToken.cdc`というファイルが表示されます。`BasicToken.cdc`には、アカウントにfungibleトークンを保存し、他のユーザーにトークンを転送したり、他のユーザーからのトークンを受け取ったりするためのコア機能を提供するfungibleトークンの完全なコードが含まれています。
:::
Cadenceで代替トークン(fungible token)を実装する際に必要となる概念は、最初は理解しにくいかもしれません。前のチュートリアルを完了しておらず、理解していない場合は、先にそちらを完了させてください。このチュートリアルでは、それらのチュートリアルで説明されている概念の多くを理解していることを前提としています。

この機能とコードの詳細については、次のセクションをお読みください。

または、すぐにデプロイしてプレイグラウンド(playground)で使用したい場合は、このチュートリアルの「[Interacting with the Fungible Token](#interacting-with-the-fungible-token-in-the-flow-playground)」セクションから読み進めてください。

<h1 id="Fungible-Tokens:An-In-Depth-Exploration">Fungible Tokens: An In-Depth Exploration</h1>

Flowが代替トークン(fungible token)を実装する方法は、他のプログラミング言語とは異なります。その結果、
* オーナーシップは分散型とされ、中央台帳に依存しません
* バグや悪用によるユーザーへのリスクや攻撃者への機会が減少します
* 整数アンダーフローやオーバーフローのリスクがありません
* 資産の重複は不可能であり、紛失、盗難、破棄される可能性は非常に低いです
* コードは構成可能(composable)です
* ルールは不変です
* コードが意図せず公開されることはありません

<h1 id="Decentralizing-Ownership">Decentralizing Ownership</h1>

中央台帳システムを使用する代わりに、Flowは資産所有の新しいパラダイムを通じて、各アカウントに所有権(オーナーシップ)を結び付けます。以下の例では、Solidity（Ethereumブロックチェーン用のスマートコントラクト言語）が代替可能なトークン(fungible token)を実装する方法を示しています。簡潔にするため、トークンの保存と転送用のコードのみを示しています。
```ruby:ERC20.sol
contract ERC20 {
    /* Maps user addresses to balances, similar to a dictionary in Cadence */
    mapping (address => uint256) private _balances;

    function _transfer(address sender, address recipient, uint256 amount) {
        /* ensure the sender has a valid balance */
        require(_balances[sender] >= amount);

        /* subtract the amount from the senders ledger balance */
        _balances[sender] = _balances[sender] - amount;

        /* add the amount to the recipient’s ledger balance */
        _balances[recipient] = _balances[recipient] + amount
    }
}
```
ご覧の通り、Solidityでは、交換可能なトークンに対して中央台帳システムを使用しています。トークンの状態を管理するスマートコントラクトが1つあり、ユーザーがトークンに対して何らかの操作を行いたい場合は、必ずERC20の中央コントラクトとやりとりを行い、その機能を利用して残高を更新する必要があります。このスマートコントラクトは、すべての機能に対するアクセス制御を処理し、独自の正確性チェックをすべて実装し、すべてのユーザーに対するルールを強制します。

中央集権型の台帳システムを使用する代わりに、Flowはスマートコントラクトの開発者やユーザーに、より高い安全性、セキュリティ、明瞭性を提供するために、いくつかの異なるコンセプトを活用しています。このセクションでは、代替可能なトークンの例を通じて、Flowのリソース、インターフェース、その他の機能がどのように使用されているかを示します。
<h1 id="Intuiting-Ownership-with-Resources">Intuiting Ownership with Resources</h1>

Cadenceにおける重要な概念は**Resources**であり、これLinear Type(リニアタイプ)す。リソース(resource)は、独自の定義済みフィールドと関数を持つ複合型（構造体のような）です。リソースオブジェクトには、コピーや損失(lost)を防ぐ特別なルールがある点が異なります。リソースは、資産所有の新しいパラダイムです。トークン所有権を中央台帳スマートコントラクトで表すのではなく、各アカウントは、アカウントストレージ(account storage)にトークンの所有数を記録しているリソース(resource)オブジェクトを所有します。これにより、ユーザー同士が取引(トランザクション)を行いたい場合、中央のトークンスマートコントラクトとやり取りすることなく、ピアツーピアで取引を行うことができます。トークンを互いに移転するには、中央の`transfer`関数ではなく、自身のリソースオブジェクトと他のユーザーのリソースに対して`transfer`関数（または同等のもの）を呼び出します。

(*補足: 各アカウントはストレージを保有しており、その中にリソースというスマートコントラクトによって生成されたインスタンスを所有します。そこからスマートコントラクトの関数を呼ぶのですが、実際にはインスタンスの関数なのでストレージ内のリソースを通じて呼び出していることになります*)

このアプローチでは、アクセス制御が簡素化されます。なぜなら、中央のスマートコントラクトが関数呼び出しの送信者をチェックする必要がないため、ほとんどの関数呼び出しはユーザーのアカウントに保存されたリソースオブジェクト上で実行され、各ユーザーは自分のアカウントのリソース上で関数を呼び出せるユーザーを制御できるからです。この概念は「Capabilityベースのセキュリティ」と呼ばれ、後のセクションで詳しく説明します。

このアプローチは潜在的なバグからの保護にも役立ちます。Solidityスマートコントラクトにすべてのロジックとステートが含まれている場合、脆弱性が存在すると、すべてのユーザが影響を受ける可能性が高いです。

Cadenceでは、リソース(resource)ロジックにバグがある場合、攻撃者は各トークンホルダーのアカウントで個別にバグを悪用する必要があり、中央台帳システムよりもはるかに複雑で時間がかかります。

以下は、fungible token vaultのリソースの例です。これらのトークンを所有するすべてのユーザーは、このリソースをアカウントに保存することになります。各アカウントには、`Vault`リソースのコピーのみ(*補足: つまり、クラスから生成されたインスタンスです。*)が保存され、`ExampleToken`スマートコントラクトのコピーは保存されないことに留意することが重要です。`ExampleToken`スマートコントラクトは、トークンの定義を管理する初期アカウント(*補足: =管理者アカウント*)にのみ保存する必要があります。
```ruby:Token.cdc
access(all)
resource Vault: Provider, Receiver {

    /* Balance of a user's Vault
       we use unsigned fixed point numbers for balances
       because they can represent decimals and do not allow negative values */
    access(all) var balance: UFix64

    init(balance: UFix64) {
        self.balance = balance
    }

    access(Withdraw) fun withdraw(amount: UFix64): @Vault {
        self.balance = self.balance - amount
        return <-create Vault(balance: amount)
    }

    access(all) fun deposit(from: @Vault) {
        self.balance = self.balance + from.balance
        destroy from
    }
}
```
このコードは教育目的であり、包括的なものではありません。しかし、トークン用のリソースがどのように機能するかを示しています。

<h1 id="Token-Balances-and-Initialization">Token Balances and Initialization</h1>

トークンリソースオブジェクトにはそれぞれ残高があり、関連する機能（`deposit`、`withdraw`など）があります。ユーザーがこれらのトークンを使用したい場合、アカウントストレージにこのリソースの残高ゼロのインスタンスを保存します。言語では、初期化関数`init`は一度だけ実行され、すべてのメンバー変数を初期化する必要があります。
```ruby
/* Balance of a user's Vault
   we use unsigned fixed-point integers for balances because they do not require the
   concept of a negative number and allow for more clear precision */
access(all) var balance: UFix64

init(balance: UFix64) {
    self.balance = balance
}
```
`init` 関数を`ExampleToken` スマートコントラクトから削除すると、残高(balance)フィールドが初期化されなくなるため、エラーが発生します。
<h1 id="Deposit">Deposit</h1>

(init処理を実行)すれば、トークンを転送する先としての任意アカウント上でdeposit関数が利用可能になります。
```ruby
access(all) fun deposit(from: @Vault) {
    self.balance = self.balance + from.balance
    destroy from
}
```

<h1 id="Transferring-Tokens">Transferring Tokens</h1>

アカウントがトークンを別のアカウントに送信したい場合、送信元のアカウントはまず自身のwithdraw関数を呼び出します。これにより、リソースの残高からトークンが差し引かれ、この残高(balance)を保持する新しいリソースオブジェクトが一時的に作成されます。
```ruby
/* Withdraw tokens from the signer's stored vault */
let sentVault <- vaultRef.withdraw(amount: amount)
```
送金側アカウントは次に、受取側アカウントのdeposit関数を呼び出します。これは文字通り、リソースインスタンスを他方のアカウントに移動し、残高に追加し、使用済みのリソースを破棄します。
```ruby
/* Deposit the withdrawn tokens in the recipient's receiver */
receiverRef.deposit(from: <-sentVault)
```
リソースは破棄する必要があります。これは、Cadenceがリソースのやり取りに関して
(Linear Typeによる)厳格なルールを適用しているためです。リソースをコード内に残しておくことはできません。明示的に破棄するか、アカウントのストレージに保存する必要があります。

リソースをやり取りする際には、`@`記号を使用して型を指定し、リソースを移動する場合には、特別な「移動演算子」`<-`を使用します。
```ruby
access(all) fun withdraw(amount: UInt64): @Vault {
```
この`@`記号は、フィールド、引数、または戻り値のリソース**タイプ(型)**を指定する際に必要となります。移動演算子`<-`は、リソースが変数等に**割り当て(assignment)*、関数のパラメータ、または戻り値に使用される場合、新しい場所に移動され、古い場所の値は無効になることを明確にします。これにより、リソースは常に1つの場所にのみ存在することが保証されます。

リソースがアカウントのストレージから移動された場合、アカウントのストレージに移動するか、明示的に破棄する必要があります。

```ruby
destroy from
```
このルールにより、実質的な価値を持つことが多いリソースが、コーディングエラーによって失われることがないようにしています。

算術演算が実際にはオーバーフローやアンダーフローに対して明示的に保護されていないことに気づくでしょう。
```ruby
self.balance = self.balance - amount
```
Solidityでは、これは整数オーバーフローまたはアンダーフローのリスクとなり得ますが、Cadenceにはオーバーフローおよびアンダーフローの保護機能が組み込まれているため、リスクにはなりません。また、この例では符号なし数値を使用しているため、前述の通り、Vaultの残高が0を下回ることはありません。

さらに、トークンのリソース型のインスタンスをアカウントのストレージに含んでいるという要件により、資金が誤ったアドレスに送信されて失われることがないようになっています。

アドレス(=アカウント)に正しいリソース型がインポートされていない(保存されていない)場合、トランザクションは取り消され、誤ったアドレスに送信されるトランザクションによって失われることはありません。

**重要：この保護機能は、Flowネットワーク通貨には適用されません。なぜなら、Flowアカウントはすべて、[ストレージ料金とトランザクション手数料](https://qiita.com/flowcadence/items/c4c24a01ec3d6b7429e2)の支払いのために、デフォルトのFlowトークンvaultで初期化されているからです。**(補足: Flowでは全てのアカウントが生成時からFlow Tokenのインスタンスを保有しています。なぜならそのトークンを使ってトランザクション費用を支払うからです)
<h1 id="Function-Parameters">Function Parameters</h1>

`withdraw`の行で新しい`Vault`(トークンの保管庫)を作成する場合、関数呼び出し時にパラメータ`balance`を指定します。
```ruby
return <-create Vault(balance: amount)
```
これも、Cadenceがコードの明瞭性を向上させるために使用する機能です。開発者が関数宣言時に要件を特に上書きしていない限り、すべての関数呼び出しでは、送信する引数の名前を指定する必要があります。
<h1 id="Interacting-with-the-Fungible-Token-in-the-Flow-Playground">Interacting with the Fungible Token in the Flow Playground</h1>

fungibleトークンの仕組みについてお読みいただいたので、あなたのアカウントにそのベーシックバージョンをデプロイし、いくつかのトランザクションを送信して、それ(fungible token)とやり取りすることができます。

:::note
ⓘ ACTION
このページの上部にあるリンクから、fungibleトークンのテンプレートをプレイグラウンド(playground)で開いていることを確認してください。Account `0x06`が開かれており、以下のコードが表示されているはずです。
:::
```ruby
/** BasicToken.cdc
   
    The BasicToken contract is a sample implementation of a fungible token on Flow.
   
    Fungible tokens behave like everyday currencies -- they can be minted, transferred or
    traded for digital goods.
   
    This is a basic implementation of a Fungible Token and is NOT meant to be used in production
    See the Flow Fungible Token standard for real examples:  */https://github.com/onflow/flow-ft

access(all) contract BasicToken {

    access(all) entitlement Withdraw

    access(all) let VaultStoragePath: StoragePath
    access(all) let VaultPublicPath: PublicPath

    /** Vault
       
        Each user stores an instance of only the Vault in their storage
        The functions in the Vault are governed by the pre and post conditions
        in the interfaces when they are called.
        The checks happen at runtime whenever a function is called.
       
        Resources can only be created in the context of the contract that they
        are defined in, so there is no way for a malicious user to create Vaults
        out of thin air. A special Minter resource or constructor function needs to be defined to mint
        new tokens.
    */
    access(all) resource Vault {

		/** keeps track of the total balance of the account's tokens
        access(all) var balance: UFix64

            initialize the balance at resource creation time */
        init(balance: UFix64) {
            self.balance = balance
        }

        /** withdraw
           
            Function that takes an integer amount as an argument
            and withdraws that amount from the Vault.
        
            It creates a new temporary Vault that is used to hold
            the money that is being transferred. It returns the newly
            created Vault to the context that called so it can be deposited
            elsewhere.
        */
        access(Withdraw) fun withdraw(amount: UFix64): @Vault {
            pre {
                self.balance >= amount:
                    "BasicToken.Vault.withdraw: Cannot withdraw tokens! "
                    .concat("The amount requested to be withdrawn (").concat(amount.toString())
                    .concat(") is greater than the balance of the Vault (")
                    .concat(self.balance.toString()).concat(").")
            }
            self.balance = self.balance - amount
            return <-create Vault(balance: amount)
        }

        /** deposit
           
            Function that takes a Vault object as an argument and adds
            its balance to the balance of the owners Vault.
           
            It is allowed to destroy the sent Vault because the Vault
            was a temporary holder of the tokens. The Vault's balance has
            been consumed and therefore can be destroyed. */
        access(all) fun deposit(from: @Vault) {
            self.balance = self.balance + from.balance
            destroy from
        }
    }

    /** createVault
       
        Function that creates a new Vault with an initial balance
        and returns it to the calling context. A user must call this function
        and store the returned Vault in their storage in order to allow their
        account to be able to receive deposits of this token type.
    */
    access(all) fun createVault(): @Vault {
        return <-create Vault(balance: 30.0)
    }

    /** The init function for the contract. All fields in the contract must
        be initialized at deployment. This is just an example of what
        an implementation could do in the init function. The numbers are arbitrary. */
    init() {
        self.VaultStoragePath = /storage/CadenceFungibleTokenTutorialVault
        self.VaultPublicPath = /public/CadenceFungibleTokenTutorialReceiver
        /* create the Vault with the initial balance and put it in storage
           account.save saves an object to the specified `to` path
           The path is a literal path that consists of a domain and identifier
           The domain must be `storage`, `private`, or `public`
           the identifier can be any name */
        let vault <- self.createVault()
        self.account.storage.save(<-vault, to: self.VaultStoragePath)
    }
}
```

:::note
ⓘ ACTION
(Playgroundの)エディタの右上にあるdeployボタンをクリックしてコードをデプロイします。
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3912821/d2699921-b3c0-8d89-96fe-7fe22a4f261d.png)

このデプロイ実施では、基本的なfungibleトークンのスマートコントラクトを、選択したアカウント（アカウント`0x06`）に保存します。これにより、そのスマートコントラクトをトランザクション実施時にインポートできるようになります。

スマートコントラクトの`init`関数は、スマートコントラクトが作成されたときに実行され、その後は決して実行されることはありません。この例では、この関数は`Vault`オブジェクトのインスタンスを初期残高(initial balance)30で保存しています。
```ruby
/* create the Vault with the initial balance and put it in storage
   account.save saves an object to the specified `to` path
   The path is a literal path that consists of a domain and identifier
   The domain must be `storage` or `public`
   the identifier can be any string */
let vault <- self.createVault()
self.account.save(<-vault, to: self.VaultStoragePath)
```
この行は、新しい`@Vault`オブジェクトをストレージに保存します。アカウントのストレージは、ドメインと識別子からなる[path](https://qiita.com/flowcadence/items/9767ec3f9b8d757d7)でインデックス化されます。`/domain/identifier`。パス名には2つのドメインのみ使用できます。
`storage`: すべてのオブジェクトが保存される場所。アカウントの所有者のみがアクセスできます。
`public`: ストレージ内のオブジェクトへのリンクを保存します。ネットワーク上の誰でもアクセスできます。

スマートコントラクトは、デプロイ先のアカウントの`self.account`を使用し、プライベートな`&Account`オブジェクトにアクセスできます。このオブジェクトには、ストレージをさまざまな方法で変更できるメソッドがあります。呼び出し可能なすべてのメソッドの一覧については、[アカウント](https://qiita.com/flowcadence/items/5ddbb79fe8438850cf57)のドキュメントを参照してください。

この行では、`storage.save`メソッドを呼び出してリソースのインスタンスをストレージに保存します。
最初の引数は保存する値で、2番目の引数は値を保存する先のパスです。`storage.save`の場合は、パスは`/storage/`ドメインでなければなりません。

これで、交換可能なトークン(fungible token)を使うトランザクションを実行する準備ができました！
<h1 id="Perform-a-Basic-Transfer">Perform a Basic Transfer</h1>

前述の通り、トークンをリソースとともに転送することは、単なる台帳の更新ではありません。Cadenceでは、まずトークンを保管庫から引き出し、次に転送先の保管庫に預け入れなければなりません。ここでは、トークンを保管庫から引き出し、同じ保管庫に預け入れるという単純なトランザクションを開始します。

:::note
ⓘ ACTION
`Basic Transfer`という名前のトランザクションを開きます。

`Basic Transfer`には、保管された保管庫からの引き出しと預け入れを行うための以下のコードが含まれているはずです。
:::
```ruby:BasicTransfer.cdc
/* Basic Transfer */

import BasicToken from 0x06

/* This transaction is used to withdraw and deposit tokens with a Vault */

transaction(amount: UFix64) {

  prepare(signer: auth(BorrowValue) &Account) {

        /* Get a reference to the signer's stored vault */
        let vaultRef = signer.storage.borrow<auth(BasicToken.Withdraw) &BasicToken.Vault>
                       (from: BasicToken.VaultStoragePath)
            ?? panic("Could not borrow a vault reference to 0x06's BasicToken.Vault"
                     .concat(" from the path ")
                     .concat(BasicToken.VaultStoragePath.toString())
                     .concat(". Make sure account 0x06 has set up its account ")
                     .concat("with an BasicToken Vault."))

        /* Withdraw tokens from the signer's stored vault */
        sentVault <- vaultRef.withdraw(amount: amount)

        /* Deposit the withdrawn tokens in the recipient's receiver */
        vaultRef.deposit(from: <-sentVault)

        log("Withdraw/Deposit succeeded!")
    }
}
```
:::note
ⓘ ACTION
アカウント`0x06`のみを署名者として選択します。
転送するトークンの数量には、30.0未満の任意の数値を入力できます。
`Send`ボタンをクリックして、トランザクションを送信します。
このトランザクションでは、main vaultからトークンをwithdrawし、それを再びmain vaultにdepositします。
:::
このトランザクションは、アカウント内での送金の基本的な例です。トークンをメインの保管庫(Vault)から引き出し、メインの保管庫(Vault)に戻します。これは、送金がどのように機能するのかという基本的な機能を説明するためのものです。

このトランザクションでは、ストレージ内のオブジェクトから参照を直接借用できることがわかります。
```ruby
/* Borrow a Withdraw reference to the signer's vault
   Remember to always have descriptive error messages! */
let vaultRef = signer.storage.borrow<auth(BasicToken.Withdraw) &BasicToken.Vault>
                (from: ExampleToken.VaultStoragePath)
    ?? panic("Could not borrow a vault reference to 0x06's BasicToken.Vault"
            .concat(" from the path ")
            .concat(BasicToken.VaultStoragePath.toString())
            .concat(". Make sure account 0x06 has set up its account ")
            .concat("with an BasicToken Vault."))
```

これにより、よりコストのかかるやりとりであるオブジェクトのロードを行うことなく、ストレージ内のオブジェクトに効率的にアクセスすることができます。

このコードでは、参照を通じてwithdraw機能にアクセスするために、エンタイトルメント（`auth(BasicToken.Withdraw)`）も使用しています。エンタイトルメントがなければ、参照は具体的な参照型にダウンスローディングできるため、特権機能はすべてパブリック機能を通じてアクセス可能になります。したがって、特権機能を持つ関数（例えば、`withdraw()`）は、安全を確保するためにエンタイトルメントを持つ必要があります。

本番コードでは、おそらくトークンを他のアカウントに転送することになるでしょう。 Capabilityにより、これを安全に実行することができます。

<h1 id="Ensuring Security in Public: Capability Security">Ensuring Security in Public: Capability Security</h1>

Cadenceのもう一つの重要な特徴は、Capabilityベースのセキュリティ（[Capability-Based Security](https://qiita.com/flowcadence/items/b70151356f4e548f2c91)）を採用していることです。

Cadenceのセキュリティモデルでは、アカウントのストレージに保存されたオブジェクトは、そのオブジェクトを所有するアカウントのみがアクセスできることを保証します。ユーザーが保存したオブジェクトへのアクセスを他のユーザーに許可したい場合、ユーザーは「API」のような公開Capabilityをリンクすることができます。これにより、他のユーザーはユーザーのオブジェクト上の指定された関数を呼び出すことができます。

アカウントは、明示的にそれらのフィールドやメソッドへのアクセスを許可するオブジェクトに対するCapabilityを保持している場合のみ、異なるアカウントのオブジェクトのフィールドやメソッドにアクセスできます。

オブジェクトの所有者のみが、そのオブジェクトに対するCapabilityを作成でき、また、所有者のみがCapabilityに権限(エンタイトルメント)を追加できます。

したがって、ユーザーが自分のアカウントでVaultを作成すると、リソース上の`access(all)`で宣言されたフィールドと関数を公開するCapabilityが保存されます。ここでは、それらは`balance`および`deposit()`です。

withdraw関数は、所有者だけが呼び出せる関数として非公開にしておくことができます。

これにより、アクセス制御の目的で関数呼び出しを行ったアカウントのアドレス（Ethereumでは`msg.sender`）を確認する必要がなくなります。なぜなら、この機能はプロトコルと言語の強力な静的型システムによって処理されるからです。オブジェクトの所有者でない場合、またはその所有者によって作成された有効な参照を持っていない場合は、オブジェクトに一切アクセスできません。
<h1 id="Using-Pre-and-Post-Conditions-to-Secure-Implementations">Using Pre and Post-Conditions to Secure Implementations</h1>

Cadenceにおける次の重要な概念は、設計によるコントラクト（design-by-contract）でありこれは、プログラムによって状態(state)が変化したことをプログラム的に警告するために、事前条件と事後条件を使用します。これらの条件は通常、型が定義されたり、動作する方法に関してルールを強制したりする[インターフェース](https://qiita.com/flowcadence/items/765a76e4fac1220ea7d9)で指定されます。

この例では、単純化のためインターフェースは使用していませんが、上記の`Vault`リソース用のインターフェースの例を以下に示します。
```ruby:Interfaces.cdc
/* Interface that enforces the requirements for withdrawing
   tokens from the implementing type
*/
access(all) resource interface Provider {
    access(Withdraw) fun withdraw(amount: UFix64): @Vault {
        post {
            // `result` refers to the return value
            result.balance == amount:
                "FungibleToken.Provider.withdraw: Cannot withdraw tokens!"
                .concat("The balance of the withdrawn tokens (").concat(result.balance.toString())
                .concat(") is not equal to the amount requested to be withdrawn (")
                .concat(amount.toString()).concat(")")
        }
    }
}
/* Interface that enforces the requirements for depositing
   tokens into the implementing type
*/
access(all) resource interface Receiver {

    /* There aren't any meaningful requirements for only a deposit function
       but this still shows that the deposit function is required in an implementation. */
    access(all) fun deposit(from: @Vault)
}

/* Balance
  
   Interface that specifies a public `balance` field for the vault
*/
access(all) resource interface Balance {
    access(all) var balance: UFix64
}
```

本番コードでは、`Vault`リソースがこれら3つのインターフェースすべてを実装します。これらのインターフェースにより、特定のフィールドと関数がリソースの実装に存在し、関数の引数、リソースのフィールド、およびすべての戻り値が実行前および/または実行後に有効な状態であることが保証されます。

これらのインターフェースはオンチェーンにデプロイすれば、他のコントラクトやリソースにインポートされることができ、これらの要件が、ヒューマンエラーの影響を受けない不変の真実のソースによって強制されるようにします(enforced by an immutable source of truth that is not susceptible to human error)。

実際のfungibleトークン実装で使用されるインターフェースについては、[Flow Fungible Token standard](https://github.com/onflow/flow-ft/blob/master/contracts/FungibleToken.cdc)を参照してください。

<h1 id="Adding-Interfaces-to-Our-Fungible-Token">Adding Interfaces to Our Fungible Token</h1>

次に、これらのインターフェースを、minterリソースとともにFungibleトークンに追加します。

`ExampleToken` スマートコントラクトを開きます。 `BasicToken` スマートコントラクトに含まれているものに加えて、`Provider`、`Receiver`、および`Balance`インターフェースをインターフェースを私たちが追加しました。 
`ExampleToken.Vault`型はこれらのインターフェースを実装することを宣言しており、それらのフィールドと関数が必要となります。また、それぞれの関数が呼び出されるたびに、事前条件と事後条件も評価されます。

さらに、`ExampleToken`は`createVault()`を`createEmptyVault()`に変更し、トークンの発行を新たに追加された`VaultMinter`リソースに制限します。これは、Cadenceリソースのもう一つの強力な機能を示しています。スマートコントラクトがminterのアドレスのリストを管理する代わりに、ミントにしたいアカウントに、トークン発行の権限を直接付与する特別なリソースを与えることができます。この認証方法は、さまざまな方法で使用でき、スマートコントラクトの管理をさらに分散化できます。

また、`VaultMinter`オブジェクトを`/storage/`に`init()`関数内で保管しますが、保管場所はVaultとは異なります。
```ruby
self.account.storage.save(<-create VaultMinter(), to: /storage/CadenceFungibleTokenTutorialMinter)
```

ここで、アカウントストレージはスマートコントラクトによって名前空間化(namespaced)されていないことを思い出していただくことが重要です。つまり、パス名が潜在的に競合する可能性があるということです。これが、他のプロジェクトのパスと競合する可能性が非常に低いように、ここで私たちがしたように、パスに一意の名前を選択することが重要である理由です。

<h1 id="Create,-Store,-and-Publish-Capabilities-and-References-to-a-Vault
">Create, Store, and Publish Capabilities and References to a Vault
</h1>

まだまだ続きますが、私は翻訳もうギブアップです。読みたい方はこちらからどうぞ👇

翻訳元

https://cadence-lang.org/docs/tutorial/fungible-tokens

***
<b>[Previous << 5.2 Non-Fungible Token Tutorial Part 2](https://qiita.com/flowcadence/items/0f791b45ca9fd289944a)
</b>

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

<b>[Next >> 7. Marketplace Setup](https://qiita.com/flowcadence/items/20c399a90a9cd9eb5250)</b>