愛記システム概念設計:愛の行動レベル② | 続・ティール組織 研究会のブログ

続・ティール組織 研究会のブログ

ティール組織が話題になっているが、具現化するにはどうしたらよいか?
その研究を続けるにあたり、さらに次の形態である、続・ティール組織なるものまで視野に入れ、具体的な施策・行動内容を研究・支援する会。

先までは、"愛記"についての記載で、どのようにブロックチェーンSNSに組み込んで実装していけばよいのか、概念的なところからアプローチ方法を記載していった。大まかな概念としてはひとまず終えた。次は、ブロックチェーンの概念設計といえるところまで、基本設計書に着手できるようなところまで、概念を具体化していきたい。

愛の行動レベルについて②:

先に、愛貨トークンは、各取引において愛の行動レベルを示すプロパティを持つことができる。これにより、特定のトークンがどのような愛の行動に関連しているかが透明になる、と記載した。愛貨トークン(Lv1からLv10)の発行を実装するには、通常、ブロックチェーンシステムのスマートコントラクト側でこの機能を処理する。愛貨トークンの各レベルは、異なるスマートコントラクトによって表され、それぞれがその特定レベルの発行、転送、およびその他の関連操作を管理する。以下は、システムにこれを統合する一般的な方法である:

  1. スマートコントラクト:愛貨トークンの各レベルに対するスマートコントラクトを開発する。これらの契約には、発行、転送、承認など、各レベルに固有の機能が含まれる必要がある。

  2. 発行ロジック:ユーザーの行動に基づいて愛貨トークンを発行するためのロジックを定義する。このロジックは、各アクションごとにいつ、どれだけのトークンが発行されるかを決定する。

  3. 承認プロセスとの統合:発行ロジックを承認プロセスに統合する。ユーザーが愛の行動を行い、トークンの発行がトリガーされると、このアクションは市町村のブロックチェーンに記録され、その後、メインチェーンで最終的に承認される前にDPoSプロセスを通じて承認される。

  4. メインチェーンとのインタラクション:愛貨トークンの発行の承認と最終化を処理するために、市町村のブロックチェーンとメインチェーンとの間で必要なインタラクションを開発する。これには、メインチェーンに承認リクエストを送信し、DPoSバリデーターによる最終的な承認を処理することが含まれる。

  5. トークンの転送メカニズム:ユーザーが愛貨トークンを互いに転送できるメカニズムを実装する。これも、各トークンレベルのスマートコントラクトによって処理される必要がある。

  6. ユーザーインターフェース:最後に、これらのスマートコントラクトとのインタラクションを可能にし、愛貨トークンの転送と管理を促進するためのSNSプラットフォームのユーザーインターフェース(UI)を設計および実装する必要がある。

全体として、愛貨トークンの発行と承認プロセスとブロックチェーンとのインタラクションは、主にスマートコントラクトロジックで処理する必要がある。メインチェーンのプログラミングは、承認プロセスの管理と取引の最終化に関わるが、市町村のブロックチェーンは、トークンの発行イベントの初期承認と記録を処理する。

スマートコントラクトのプログラム

では、上記の一つずつを見ていこう。スマートコントラクトのプログラムをきちんとやっていくためにも、一つずつ確実にやっていく必要がある。

1.スマートコントラクト:愛貨トークンの各レベルに対するスマートコントラクトを開発する。これらの契約には、発行、転送、承認など、各レベルに固有の機能が含まれる必要がある。

// 愛貨トークンの状態を管理する構造体
struct LoveCurrencyToken {
    mapping(address => uint) balance;
    uint totalSupply;
    mapping(address => bool) approved;
    uint approvalCount;
    address owner;
}

// 愛貨トークンを発行するスマートコントラクト
contract LoveCurrencyLv1 {
    LoveCurrencyToken public token;

    constructor() {
        token = new LoveCurrencyToken();
        token.owner = msg.sender; // コントラクトのデプロイヤーを所有者として設定
    }

    // 愛貨トークンを発行する関数
    function issueToken(address recipient, uint amount) public {
        require(msg.sender == token.owner, "Only the owner can issue tokens.");
        token.balance[recipient] += amount;
        token.totalSupply += amount;
    }

    // 愛貨トークンを送信する関数
    function transfer(address to, uint amount) public {
        require(token.balance[msg.sender] >= amount, "Insufficient balance.");
        token.balance[msg.sender] -= amount;
        token.balance[to] += amount;
    }

    // 他のアカウントに対してトークンの承認をする関数
    function approve(address spender, uint amount) public {
        require(token.balance[msg.sender] >= amount, "Insufficient balance.");
        token.approved[spender] = true;
        token.approvalCount++;
    }

    // 他のアカウントに対するトークンの承認を取り消す関数
    function revokeApproval(address spender) public {
        require(token.approved[spender], "Approval not granted.");
        token.approved[spender] = false;
        token.approvalCount--;
    }
}

// 同様にLv2からLv10までのスマートコントラクトも作成
contract LoveCurrencyLv2 { /* ... */ }
// ...
contract LoveCurrencyLv10 { /* ... */ }

 

上記のスマートコントラクトは、愛貨トークン(Lv1からLv10)を管理するためのものである。それぞれのレベルに対応するスマートコントラクトがあり、それぞれのスマートコントラクトには以下の機能が含まれている:

  1. issueToken:トークンの発行を行う。発行者のみが発行でき、指定した受取人にトークンを送る。

  2. transfer:トークンの送金を行う。送信者がトークンを持っていることを確認し、指定した受取人にトークンを送る。

  3. approve:特定のアドレスに対して、一定量のトークンを承認する。承認されたアドレスは、承認されたトークン量内で送金を行うことができる。

  4. revokeApproval:特定のアドレスへのトークンの承認を取り消す。

これらの機能を使って、各レベルの愛貨トークンを発行し、送金や承認を行うことができる。各レベルのスマートコントラクトは、それぞれ独立して動作し、異なるレベルのトークンを管理する。

 

 

2.発行ロジック:ユーザーの行動に基づいて愛貨トークンを発行するためのロジックを定義する。このロジックは、各アクションごとにいつ、どれだけのトークンが発行されるかを決定する。以下は、指定された10種類の愛貨トークンを扱うスマートコントラクトのRustプログラムであり、ユーザーの行動に基づいて各アクションごとに適切な愛貨トークンを発行する。

#![no_std]
#![feature(proc_macro_hygiene)]

use ink_lang::contract;

#[contract]
pub mod love_currency {
    use ink_core::storage;
    use ink_core::env;

    #[storage]
    pub struct LoveCurrency {
        // 各レベルのトークンのバランスを保持
        pub air: storage::Value<Balance>,
        pub ais: storage::Value<Balance>,
        pub aip: storage::Value<Balance>,
        pub aih: storage::Value<Balance>,
        pub ait: storage::Value<Balance>,
        pub aii: storage::Value<Balance>,
        pub aic: storage::Value<Balance>,
        pub aiu: storage::Value<Balance>,
        pub aie: storage::Value<Balance>,
        pub aim: storage::Value<Balance>,
    }

    #[derive(Debug, scale::Encode, scale::Decode, PartialEq, Eq, Copy, Clone)]
    #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
    pub struct Balance {
        value: u64,
    }

    impl Balance {
        pub fn new(value: u64) -> Self {
            Self { value }
        }

        pub fn add(&mut self, value: u64) {
            self.value += value;
        }

        pub fn sub(&mut self, value: u64) {
            self.value -= value;
        }
    }

    impl LoveCurrency {
        #[ink(constructor)]
        pub fn new() -> Self {
            Self {
                air: storage::Value::new(default_balance()),
                ais: storage::Value::new(default_balance()),
                aip: storage::Value::new(default_balance()),
                aih: storage::Value::new(default_balance()),
                ait: storage::Value::new(default_balance()),
                aii: storage::Value::new(default_balance()),
                aic: storage::Value::new(default_balance()),
                aiu: storage::Value::new(default_balance()),
                aie: storage::Value::new(default_balance()),
                aim: storage::Value::new(default_balance()),
            }
        }

        #[ink(message)]
        pub fn issue_token(&mut self, level: u8) {
            let mut token = match level {
                1 => &mut self.air,
                2 => &mut self.ais,
                3 => &mut self.aip,
                4 => &mut self.aih,
                5 => &mut self.ait,
                6 => &mut self.aii,
                7 => &mut self.aic,
                8 => &mut self.aiu,
                9 => &mut self.aie,
                10 => &mut self.aim,
                _ => return,
            };
            token.add(1); // 1つのトークンを発行
        }

        #[ink(message)]
        pub fn transfer_token(&mut self, level: u8, amount: u64) {
            let mut sender_token = match level {
                1 => &mut self.air,
                2 => &mut self.ais,
                3 => &mut self.aip,
                4 => &mut self.aih,
                5 => &mut self.ait,
                6 => &mut self.aii,
                7 => &mut self.aic,
                8 => &mut self.aiu,
                9 => &mut self.aie,
                10 => &mut self.aim,
                _ => return,
            };
            if sender_token.value >= amount {
                sender_token.sub(amount);
                // 送信者からamountのトークンを減算し、他の処理(送信先に追加など)を行う
                // ここでは簡略化のため省略
            }
        }

        #[ink(message)]
        pub fn get_balance(&self, level: u8) -> u64 {
            match level {
                1 => self.air.value,
                2 => self.ais.value,
                3 => self.aip.value,
                4 => self.aih.value,
                5 => self.ait.value,
                6 => self.aii.value,
                7 => self.aic.value,
                8 => self.aiu.value,
                9 => self.aie.value,
                10 => self.aim.value,
                _ => 0,
            }
        }
    }

    fn default_balance() -> Balance {
        Balance::new(0)
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[test]
        fn test_issue_token() {
            let mut contract = LoveCurrency::new();
            assert_eq!(contract.get_balance(1), 0);
            contract.issue_token(1);
            assert_eq!(contract.get_balance(1), 1);
        }

        #[test]
        fn test_transfer_token() {
            let mut contract = LoveCurrency::new();
            contract.issue_token(1);
            contract.transfer_token(1, 1);
            assert_eq!(contract.get_balance(1), 0);
        }
    }
}

なお、愛貨のレベル付きトークンは以下の10種類ある。amountで愛貨をやりとりしているが、愛貨は10種類あるから、それらをやりとりするようになっている。

Lv1:AIR(Root) 

Lv2:AIS(Sacral) 

Lv3:AIP(solar Plexus) 

Lv4:AIH(Heart) 

Lv5:AIT(Throat) 

Lv6:AII(ThIrd Eye) 

Lv7:AIC(Crown) 

Lv8:AIU(Universal) 

Lv9:AIE(Earth Star) 

Lv10:AIM(solar Matrix)

 

 

5.トークンの転送メカニズム:ユーザーが愛貨トークンを互いに転送できるメカニズムを実装する。これも、各トークンレベルのスマートコントラクトによって処理される必要がある。以下は、10種類の愛貨トークンをやりとりするためのスマートコントラクトのプログラムである。

#![cfg_attr(not(feature = "std"), no_std)]

use ink_lang as ink;

#[ink::contract]
mod love_currency {
    #[ink(storage)]
    pub struct LoveCurrency {
        balances: ink_storage::collections::HashMap<AccountId, ink_storage::collections::HashMap<u8, Balance>>,
    }

    #[derive(Debug, PartialEq, Eq, scale::Encode, scale::Decode)]
    #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
    pub struct Balance {
        value: u64,
    }

    impl Balance {
        pub fn new(value: u64) -> Self {
            Self { value }
        }

        pub fn add(&mut self, value: u64) {
            self.value += value;
        }

        pub fn sub(&mut self, value: u64) {
            if self.value >= value {
                self.value -= value;
            }
        }
    }

    impl LoveCurrency {
        #[ink(constructor)]
        pub fn new() -> Self {
            Self {
                balances: Default::default(),
            }
        }

        #[ink(message)]
        pub fn issue_token(&mut self, recipient: AccountId, level: u8) {
            let balance_map = self
                .balances
                .entry(recipient)
                .or_insert_with(|| ink_storage::collections::HashMap::new());

            let balance = balance_map
                .entry(level)
                .or_insert_with(|| Balance::new(0));

            balance.add(1);
        }

        #[ink(message)]
        pub fn transfer_token(&mut self, recipient: AccountId, sender: AccountId, level: u8, amount: u64) {
            let sender_balance_map = self.balances.get_mut(&sender);
            let recipient_balance_map = self
                .balances
                .entry(recipient)
                .or_insert_with(|| ink_storage::collections::HashMap::new());

            if let Some(sender_balance_map) = sender_balance_map {
                if let Some(sender_balance) = sender_balance_map.get_mut(&level) {
                    if sender_balance.value >= amount {
                        sender_balance.sub(amount);
                        let recipient_balance = recipient_balance_map
                            .entry(level)
                            .or_insert_with(|| Balance::new(0));
                        recipient_balance.add(amount);
                    }
                }
            }
        }

        #[ink(message)]
        pub fn get_balance(&self, account: AccountId, level: u8) -> u64 {
            if let Some(balance_map) = self.balances.get(&account) {
                if let Some(balance) = balance_map.get(&level) {
                    return balance.value;
                }
            }
            0
        }
    }

    #[cfg(test)]
    mod tests {
        use super::*;

        #[ink::test]
        fn issue_token_works() {
            let mut contract = LoveCurrency::new();
            let alice = AccountId::from([1; 32]);
            contract.issue_token(alice, 1);
            assert_eq!(contract.get_balance(alice, 1), 1);
        }

        #[ink::test]
        fn transfer_token_works() {
            let mut contract = LoveCurrency::new();
            let alice = AccountId::from([1; 32]);
            let bob = AccountId::from([2; 32]);
            contract.issue_token(alice, 1);
            contract.transfer_token(bob, alice, 1, 1);
            assert_eq!(contract.get_balance(alice, 1), 0);
            assert_eq!(contract.get_balance(bob, 1), 1);
        }
    }
}
上記のスマートコントラクトは、10種類の愛貨トークンを管理するためのものであり、以下が主な機能の説明である:
・LoveCurrency構造体:balances フィールドは、ユーザーごとに各愛貨トークンの残高を格納するためのHashMapである。
・Balance構造体:トークンの残高を表す構造体で、value フィールドに残高が格納される。
・issue_tokenメソッド:recipient パラメータに指定されたアカウントに、指定されたレベルの愛貨トークンを1つ発行する。指定されたアカウントが存在しない場合は、新しいアカウントを作成する。
・transfer_tokenメソッド:sender から recipient へ、指定されたレベルの愛貨トークンを指定された量だけ転送する。送信者の残高が不足している場合は、転送は行われない。
・get_balanceメソッド:指定されたアカウントとレベルに対する残高を取得する。
・テスト:issue_token_works テストでは、愛貨トークンが正常に発行されることを確認している。transfer_token_works テストでは、愛貨トークンが正常に転送されることを確認している。


このスマートコントラクトを使うと、ユーザーは愛貨トークンを発行したり、転送したりすることができる。各ユーザーの残高は、コントラクト内のHashMapで追跡される。スマートコントラクトは、ユーザーごとに各愛貨トークンの残高を管理し、トークンの発行や転送を処理するためのものである。愛貨の種類やレベルは、トランザクションやその他のロジックで考慮される必要があります。例えば、特定のレベルの愛貨を発行する際には、トランザクション内でそのレベルを指定する必要がある。これは以前に記載したとおり、どのレベルの愛の行動か、プログラムでは判断できないからだ。

 

 

いかがであろうか、これが愛の行動レベルごとに愛貨10種類のそれぞれを発行するスマートコントラクトのプログラム例であった。このように、愛貨を10種類設けることで、後に、変動相場制を導入した際には、世界中の愛の行動で愛貨の市場価値が乱高下する様子が実現できる。まだまだ改良の余地はあるが。