huahua

huahua

手取り足取りでトークンスワップを実現する方法を教えます!Move言語とSuiチェーンの開発実践

系列文章目录#

Task1:こんにちはムーブ🚪
Task2:ムーブコイン🚪
Task3:ムーブ NFT🚪
Task4:ムーブゲーム🚪
Task5:ムーブスワップ🚪
Task6:SDK PTB🚪

もっと素晴らしいコンテンツをお楽しみに!✌️


@TOC


前言#

前回の記事《Task4:ムーブゲーム》では、Move プログラミング言語がブロックチェーン上のインタラクティブゲームにどのように応用されるかを探求し、実用的な価値を持つじゃんけんゲームのスマートコントラクトを実装しました。このタスクを通じて、資金プールの管理、ブロックチェーン上の公平性の確保、スマートコントラクトを基にしたゲームインタラクションの重要な技術を学び、Move に対する理解と実践をさらに深めました。

本記事では、Task5: ムーブスワップに焦点を当て、Move に基づくトークンスワップのスマートコントラクトを実現する挑戦を行います。このタスクを通じて、ユーザーがブロックチェーン上で 2 種類のトークンを安全かつ迅速に交換できる基本モデルを構築します。本タスクは、Move が分散型金融(DeFi)分野での潜在能力をさらに示し、以下の重要な技術ポイントを習得する手助けをします:

  • ブロックチェーン上のトークンプールを設計・管理する方法;
  • スマートコントラクトを通じてトークンスワップのビジネスロジックを実現する方法;
  • トークンスワップの安全性と効率を確保する方法。

実装過程では、task2で定義した 2 種類のトークンHUAHUAHUA1223_COINHUAHUAHUA1223_FAUCET_COINを使用し、交換比率を設定してトークンの相互交換を実現します。また、スマートコントラクトにおける資金検証と残高管理公平性と堅牢性の設計などの核心問題についても深く探求します。

Move の応用シーンを引き続き解き放ち、分散型金融の基盤コンポーネントを一緒に構築しましょう!

HOH コミュニティ


Sui チェーンとは?#

Suiは、高性能なブロックチェーンプラットフォームで、分散型アプリケーションに迅速、安全、かつスケーラブルなインフラを提供することを目的としています。これはAptos Labsチームによって開発され、新しいコンセンサスプロトコルであるNarwhal & Tuskに基づいています。Sui の設計目標は、ブロックチェーンの性能ボトルネックを解決し、非常に高い取引スループットと低遅延を提供し、複雑なアプリケーションシーンのニーズに適応することです。

Sui チェーンの主な特徴:

  1. 高スループットと低遅延:Sui のコンセンサスメカニズムは、大量の取引を並行処理することを可能にし、ネットワーク全体のグローバルコンセンサスを待つ必要がありません。この並行化設計により、毎秒数千の取引を処理でき、ブロックチェーンのスループットが大幅に向上し、取引確認の遅延が減少します。

  2. オブジェクト指向のリソース管理:Sui は、ブロックチェーン内のリソースをオブジェクトとして管理します。これらのリソース(トークンや NFT など)は独立した識別子を持ち、直接追跡および操作できます。この方法により、Sui は複数のノード間で効率的にリソースを並行処理でき、グローバルステートを処理する必要がなく、性能がさらに向上します。

  3. 柔軟な取引モデル:Sui は、複数のリソースオブジェクト間で並行して取引を実行できる柔軟で効率的な取引モデルを提供します。これにより、異なるユーザーの取引が独立して効率的に行われ、従来のブロックチェーンの性能ボトルネックを回避できます。

  4. 効率的なアカウントと権限管理:Sui は、多様なアカウント管理メカニズムを提供し、分散型アプリケーションにおける複雑な権限要求に対応します。個人アカウント、スマートコントラクトアカウント、マルチシグアカウントなど、柔軟に構成および管理できます。


Move プログラミング言語とは?#

Moveは、ブロックチェーン開発のために特別に設計されたプログラミング言語で、最初はMetaLibra(後のDiem)チームによって開発され、その後Suiブロックチェーンに採用されました。Move の設計の重点は、リソースの管理、所有権の制御、および型安全性であり、特に分散型アプリケーション内の資産やデジタルリソースを処理するのに適しています。

Move 言語の主な特徴:

  1. リソース型システム:Move 言語は、すべてのリソース(トークン、NFT、スマートコントラクト内のデータなど)を「リソース型」として扱います。これらのリソースは、システム内でコピーまたは破壊することができず、移転または借用のみが可能です。これにより、各リソースの唯一性と安全性が確保され、従来のスマートコントラクトにおけるリソースの喪失や重複移転の問題を根本的に回避します。

  2. 所有権と借用メカニズム:Move は、厳格な所有権と借用メカニズムを通じてリソースを管理します。各リソースには唯一の所有者があり、リソースの借用は明示的に宣言する必要があります。このメカニズムは、「共有リソース」の際の安全上のリスクを回避します。リソースの借用は、開発者がリソースの所有権を変更することなく、リソースを共有および操作できることを保証します。

  3. モジュール化プログラミング:Move は、モジュール化されたプログラミング構造をサポートし、各モジュールには異なるリソース型や関数を含めることができます。モジュール化設計により、コードがより明確で再利用可能になり、開発効率が向上し、コードのエラーの可能性が低下します。

  4. 型安全性と検証可能性:Move は強い型の言語であり、開発者はコンパイル時に各変数やリソースの型を明示的に定義する必要があります。Move の型システムは、契約内のほとんどのエラーがコンパイル段階で発見されることを保証し、実行時エラーを回避し、スマートコントラクトの安全性を向上させます。

Move 言語のサンプルコード:
以下は、Coinというリソースを作成し、移転する方法を示す簡単な Move コントラクトの例です:

address 0x1 {
    module CoinModule {
        resource struct Coin has store {
            value: u64,
        }

        public fun create_coin(value: u64): Coin {
            Coin { value }
        }

        public fun transfer_coin(coin: Coin, recipient: address): Coin {
            let new_coin = Coin { value: coin.value };
            // ここで実際の送金操作を実行できます
            return new_coin;
        }
    }
}

この例では、Coinはリソース型で、トークンの値を示すvalueフィールドを含んでいます。create_coin関数は新しいCoinリソースを作成し、transfer_coin関数はCoinリソースを指定されたアカウントに移転します。


Move 共学活動:Move 開発を迅速に始める#

より多くの開発者が Move プログラミング言語を迅速に理解し習得できるように、Move 共学活動がHOH コミュニティHackQuestOpenBuildKeyMapによって共同で発起されました。この活動は、新しい初心者に良好な学習プラットフォームを提供し、皆さんが Move 言語に慣れ、Web3 開発にどのように応用できるかを理解する手助けをします。

Move 分野の専門のメンターと協力することで、参加者は Move 言語の基本知識を迅速に習得し、徐々により複雑なアプリケーション開発に進むことができます。ブロックチェーン初心者から一定の開発経験を持つエンジニアまで、誰もが恩恵を受けることができます。

リソースリンク:

  • Sui 公式ドキュメント🚪:Sui チェーンに関する詳細なドキュメントを取得し、開発ガイド、API リファレンスなどを含みます。
  • Move 学習 Bilibili 動画🚪:Bilibili のビデオチュートリアルを通じて、メンターに従って Move プログラミング言語の基礎と進階を学びます。
  • letsmove リポジトリ🚪:これは Move 学習リソースの GitHub リポジトリで、さまざまなサンプルコードやチュートリアルが含まれており、開発者が Move 言語を習得するのを助けます。

一、プロジェクトの作成#

まず、新しい Move プロジェクトを作成し、Task2で開発したトークンコントラクトをインポートする必要があります。

1.1 新しい Move プロジェクトの作成#

以下のコマンドを実行して、my_swapという名前の Move プロジェクトを作成します:

sui move new my_swap
cd .\my_swap\

ここに画像の説明を挿入

1.2 依存関係のインポート#

私たちのトークンコントラクトがすでにmy_coinディレクトリに実装されていると仮定します。次の方法でそれを新しいプロジェクトに依存関係としてインポートできます:

my_coin = { local = "../../task2/my_coin" }

ここに画像の説明を挿入

この基盤の上に、プロジェクトを空でコンパイルし、依存関係が正しくインポートされ、プロジェクトが正常にコンパイルされることを確認します:sui move build
ここに画像の説明を挿入

二、コントラクト設計#

コントラクトコード部分は、実際には前回のtask4で説明したコードロジックと同様です。task4では1 種類のトークンの入出金とゲームの勝敗のプレイを行ったため、task5ではPoolトークンプールにもう 1 種類のトークンを追加し、トークンプール内で自動的に 2 種類のトークンの変換を行うだけです。

以下はトークンスワップコントラクトの完全な実装コードで、核心ロジックを段階的に分解していきます:

module my_swap::my_swap;

use my_coin::huahuahua1223_coin::HUAHUAHUA1223_COIN;
use my_coin::huahuahua1223_faucet_coin::HUAHUAHUA1223_FAUCET_COIN;
use sui::balance::{Self, Balance};
use sui::coin::{Self, Coin, from_balance, into_balance};
use sui::transfer::{share_object, transfer, public_transfer};

const EInputNotEnough: u64 = 1000;
const EPoolNotEnough: u64 = 1001;

public struct AdminCap has key {
    id: UID
}

public struct Pool has key {
    id: UID,
    huahuahua1223_faucet_coin: Balance<HUAHUAHUA1223_FAUCET_COIN>,
    huahuahua1223_coin: Balance<HUAHUAHUA1223_COIN>,
}

fun init(ctx: &mut TxContext) {
    let pool = Pool {
        id: object::new(ctx),
        huahuahua1223_faucet_coin: balance::zero<HUAHUAHUA1223_FAUCET_COIN>(),
        huahuahua1223_coin: balance::zero<HUAHUAHUA1223_COIN>(),
    };

    let admin = AdminCap { id: object::new(ctx) };

    // 公開スワッププール
    share_object(pool);
    // 管理者権限をコントラクトデプロイ者に付与
    transfer(admin, ctx.sender());
}

2.1 トークンプールと管理者権限#

Pool構造体を通じて 2 種類のトークンの残高を維持し、同時にAdminCap構造体を設定して、管理者がトークンを引き出したり管理したりする権限を持つことを確保します。init関数はトークンプールを初期化し、管理者権限をコントラクトデプロイ者に付与します。

2.2 トークンの保管#

ユーザーはトークンプールに 2 種類のトークンのいずれかを預けることができます。以下は HUAHUAHUA1223_COIN を保管するロジックです:

// my_coinトークンを保管
public entry fun deposit_my_coin(
    pool: &mut Pool,
    user_coin: Coin<HUAHUAHUA1223_COIN>,
    amount: u64,
    ctx: &mut TxContext,
) {
    // ウォレットのトークンが入力金額より多いか確認
    let coin_value = user_coin.value();
    assert!(coin_value >= amount, EInputNotEnough);

    // CoinをBalanceに変換
    let mut input_balance = into_balance(user_coin);
    if (coin_value == amount) {
        // 入力のamountがすべてのトークン
        balance::join(&mut pool.huahuahua1223_coin, input_balance);
    } else {
        balance::join(
            &mut pool.huahuahua1223_coin,
            balance::split(&mut input_balance, amount),
        );
        // 残りのトークンを返却
        let surplus_coin = from_balance(input_balance, ctx);
        public_transfer(surplus_coin, ctx.sender());
    };
}

ここでの重要なポイントは:

  • 入力トークンの数量が十分であることを確認します。
  • 残りのトークンを処理し、ユーザーに返却します。

同様のロジックはHUAHUAHUA1223_FAUCET_COINの保管にも適用されます。

2.3 トークンの引き出し#

管理者はプール内の任意のトークンを引き出すことができます。これには管理者権限AdminCapが必要です:

// 管理者がmy_coinトークンを引き出す
public entry fun withdraw_coin(
    _: &AdminCap,
    pool: &mut Pool,
    amount: u64,
    ctx: &mut TxContext,
) {
    assert!(pool.huahuahua1223_coin.value() >= amount, EPoolNotEnough );

    // from_balanceを使用してbalanceをcoin型に変換
    let withdrawn_balance = balance::split(&mut pool.huahuahua1223_coin, amount);
    let withdrawn_coin = from_balance(withdrawn_balance, ctx);
    public_transfer(withdrawn_coin, ctx.sender());
}

// 管理者がfaucet_coinトークンを引き出す
public entry fun withdraw_faucet_coin(
    _: &AdminCap,
    pool: &mut Pool,
    amount: u64,
    ctx: &mut TxContext,
) {
    assert!(pool.huahuahua1223_faucet_coin.value() >= amount, EPoolNotEnough );

    // from_balanceを使用してbalanceをcoin型に変換
    let withdrawn_balance = balance::split(&mut pool.huahuahua1223_faucet_coin, amount);
    let withdrawn_coin = from_balance(withdrawn_balance, ctx);
    public_transfer(withdrawn_coin, ctx.sender());
}

この部分のロジックは、プール内の残高が十分であることを厳密に確認し、引き出し失敗を防ぎます。

2.4 トークンスワップ#

トークンプールの核心機能は、2 種類のトークンの相互交換を実現することです。以下にそれぞれの交換ロジックを示します:

  • faucet_coin から my_coin への交換
// 2つのfaucet_coinを1つのmy_coinに変換
public entry fun swap_faucet_coin_to_my_coin(
    pool: &mut Pool,
    user_coin: Coin<HUAHUAHUA1223_FAUCET_COIN>,
    amount: u64,
    ctx: &mut TxContext,
) {
    // スワッププールがこれだけのhuahuahua1223_coinを交換できるか確認
    let output_value = amount * 1000 / 2000;
    assert!(pool.huahuahua1223_coin.value() >= output_value, EPoolNotEnough);

    // faucet_coinをスワッププールに預けて交換を待つ
    deposit_faucet_coin(pool, user_coin, amount, ctx);

    // 半分の数量のhuahuahua1223_coinを交換
    let output_balance = balance::split(&mut pool.huahuahua1223_coin, output_value);
    let output_coin = from_balance(output_balance, ctx);
    public_transfer(output_coin, ctx.sender());
}
  • my_coin から faucet_coin への交換
// 1つのmy_coinを2つのfaucet_coinに変換
public entry fun swap_my_coin_to_faucet_coin(
    pool: &mut Pool,
    user_coin: Coin<HUAHUAHUA1223_COIN>,
    amount: u64,
    ctx: &mut TxContext,
) {
    // スワッププールがこれだけのhuahuahua1223_faucet_coinを交換できるか確認
    let output_value = amount * 2000 / 1000;
    assert!(pool.huahuahua1223_faucet_coin.value() >= output_value, EPoolNotEnough);

    // my_coinをスワッププールに預けて交換を待つ
    deposit_my_coin(pool, user_coin, amount, ctx);

    // 2倍のhuahuahua1223_faucet_coinを交換
    let output_balance = balance::split(&mut pool.huahuahua1223_faucet_coin, output_value);
    let output = from_balance(output_balance, ctx);
    public_transfer(output, ctx.sender());
}

上記のロジックにより、ユーザーは事前定義された比率(例えば2:1または1:2)に基づいて 2 種類のトークンを自由に交換できます。

2.5 メインネットデプロイ#

  1. メインネットに接続していない場合は、このチュートリアルの第 3 部🚪を参照し、その後コントラクトプロジェクトのルートディレクトリ(例:my_swap)で以下のコマンドを実行してコントラクトをデプロイします:
sui client publish --skip-dependency-verification
  1. デプロイ後、トランザクションハッシュが得られます。この値を記録し、suivision ブロックチェーンブラウザ🚪を使用してコントラクトの詳細を確認します。
    ここに画像の説明を挿入
  2. コントラクトの詳細にあるPackage IDを見つけ、フロントエンドまたはSui CLIテストツールでコントラクト関数を呼び出します。
    ここに画像の説明を挿入

三、テストと検証#

コントラクトのデプロイが完了した後、重要な機能の呼び出しをテストして、my_swapコントラクトの正確性と安定性を確認します。以下のテストには、トークンの預け入れ引き出しと交換の完全なプロセスが含まれ、重要な操作の結果と検証が記録されています。
ここに画像の説明を挿入

環境準備#

テストを開始する前に、アカウントに十分なtask2トークンがあることを確認してください。テストを容易にするために、Sui CLI を使用してアカウントに 100 個のcoinと 100 個のfaucet_coinを再鋳造しました。鋳造コマンドに不慣れな場合は、以前のTask2 チュートリアル🚪を参照してください。
ここに画像の説明を挿入

以下はアカウントの初期状態です:

  • coinトークンの数量:100
  • faucet_coinトークンの数量:100

ここに画像の説明を挿入

3.1 トークンの預け入れ#

まず、deposit関数を呼び出して、一部のトークンをプールに預けます。
操作 1:20 個の faucet_coin を預け入れる
ここに画像の説明を挿入

操作 2:20 個の coin を預け入れる
ここに画像の説明を挿入

結果の検証:
アカウントの残りのcoin数量:80
アカウントの残りのfaucet_coin数量:80
ここに画像の説明を挿入

3.2 トークンの引き出し#

次に、withdraw関数を呼び出して、管理者権限を使用して資金プールからトークンを引き出します。

操作 1:6 個のfaucet_coinを引き出す
管理者は以下のコマンドを使用して 6 個のfaucet_coinを引き出します(トークンの精度は 8 であるため、600000000 は 6 個のトークンを示します):
ここに画像の説明を挿入

操作 2:6 個のcoinを引き出す
ここに画像の説明を挿入

結果の検証:
管理者アカウントに 6 個のcoinが追加されました。
管理者アカウントに 6 個のfaucet_coinが追加されました。
ここに画像の説明を挿入

3.3 トークンスワップ#

最後に、swap関数を呼び出して 2 種類のトークンの相互交換機能を検証し、交換比率が正しいことを確認します。

操作 1:6 個のfaucet_coinを使用して 3 個のcoinを取得、交換比率は2:1
ここに画像の説明を挿入
結果の検証:
ユーザーアカウントに 3 個のcoinが追加され、合計 89 個になります。
ユーザーアカウントから 6 個のfaucet_coinが減少し、合計 80 個になります。
ここに画像の説明を挿入

操作 2:5 個のfaucet_coinを使用して 10 個のcoinを取得、交換比率は1:2
ここに画像の説明を挿入
結果の検証:
ユーザーアカウントから 5 個のcoinが減少し、合計 84 個になります。
ユーザーアカウントに 10 個のfaucet_coinが追加され、合計 90 個になります。
ここに画像の説明を挿入

上記のテストを通じて、my_swapコントラクトの各機能が検証されました:

  1. トークンを預け入れる際、残高が正しく減少し、余剰部分の返却メカニズムが有効です。
  2. トークンを引き出す際、管理者権限の検証が正確で、引き出しロジックが正確です。
  3. トークンの相互交換時、交換比率が正確で、資金プールとアカウントの残高が正常に更新されます。

これにより、Task5:トークンスワップコントラクトが無事に完了しました 🎉!

今後の挑戦:次のステップとして、動的価格設定や流動性プールの設計など、より複雑なロジックに挑戦し、分散型金融の無限の可能性を探求していきましょう!


まとめ#

本記事を通じて、あなたは Move 言語を利用して Sui チェーン上にシンプルなトークンスワップコントラクトを構築する方法を習得し、トークンの入出金、引き出し、交換の基本ロジック設計に慣れることができたはずです。この文章が DeFi 開発の入門段階で実用的なガイダンスを提供し、Move プログラミング言語と Sui ブロックチェーンに対する理解を深める助けとなることを願っています。

DeFi アプリケーション開発や Move 言語に興味がある方は、今後の文章やプロジェクトの共有をぜひご覧ください!疑問やアイデアがあれば、コメント欄で私と交流してください🌹


もっと素晴らしいコンテンツをお楽しみに!
私たちは Move の道を共に探求し、成長していきます。お見逃しなく! 🎉

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。