💸

お金を再考する - ICPで実装する地域通貨10のアイディア【ICP ハッカソン】

2025/02/10に公開
1

『本プロジェクトは、Internet Computer Protocol (ICP) を基盤とした新しい地域通貨の実装を通じて、お金の本質を再考する試みです。

プロジェクトの概要

本プロジェクトでは、ICPを活用して新しい価値交換の仕組みを実験的に構築することを目指します。
従来の通貨が持つ10の性質を意図的に覆すトークン設計を特徴とし、ICPの上でトークンを発行・流通させます。
「老化する貨幣」や「任意通用」といった独自の機能を実装することで、通貨の本質を問い直す思考実験の場を提供します。

背景:通貨の本質を問い直す

トークン発行やNFTプロジェクトの経験を重ねてきましたが、トークンの本質的な意義や在るべき姿について正解を探し続けています。

やがて、トークンの本質について向き合うには「お金」や「金融」、「経済」から掘り下げるべきだと思うようになりました。

最近この課題意識に向き合うようになったきっかけが、サイファーパンクな友人medy洗脳熱心な説得や、彼に布教されたインディーズ映画『ロマンティック金銭感覚』です。
地域通貨を通して「お金」の本質に迫る問題提起を行う作品です。

『ロマンティック金銭感覚』」は、お金の本質と私たちの生き方を問いかける作品です。
児童文学作家ミヒャエル・エンデの『エンデの遺言』から着想を得ており、1999年のNHKドキュメンタリーで取り上げられた「お金の支配からの自由」という問いかけを出発点としています。
佐伯監督は、この「地域通貨」の概念に魅了され、映画化を模索していました。2021年、共同制作者とともに東京を離れ、地方での新しい暮らしを始めたことをきっかけに、本作の制作が本格的に動き出します。古民家コミュニティやエコヴィレッジ、電子地域通貨を発行する非営利企業など、資本主義の枠組みとは異なる場所での取材を重ねていきました。
最終的に完成した作品は、従来のドキュメンタリーの形式を超えた斬新な構成となっています。実在する共生的な経済の取り組みを描くドキュメンタリーパートと、幻想的なフィクションパートを織り交ぜることで、新しい価値観や経済のあり方を模索する物語が紡ぎ出されています。それは単なる経済や通貨の記録ではなく、私たちの社会や生き方そのものを見つめ直すきっかけを提供する作品となっています。

通貨が持つ10の本質的な性質

通貨にはさまざまな機能と性質があります。
ここでは10個をピックアップし、トークン実装においてカウンターテーマとして扱います。

  1. 物理的エンティティ - 紙幣や硬貨など実体を持つ
  2. 価値の保存 - 時間が経っても価値を維持し、価値の保存と移転ができる
  3. 効率的な価値交換 - コミュニケーションを省略して、通貨のやり取りだけで取引が成立する
  4. 強制通用力 - 法的に支払い手段として認められ、支払いや受け取りを拒否できない
  5. 決済手段 - 債務や取引の支払いに使用できる
  6. 客観的な価値尺度 - あらゆる価格や価値が数値化され、公平に比較可能
  7. 貯蓄の魔力 - 手放すのではなく多く溜め込み、保有し続けたくなる心理が働く
  8. 匿名性 - 取引時に個人情報を明かさずに使用でき、使用履歴も追跡されない(※現金の場合。世界で最もマネーロンダリングに使用されているのは仮想通貨ではなく現金)
  9. 中央集権 - 政府など強力な権力の裏付けを持つ主体が発行し、流通する
  10. 法規制の適用: 通貨の発行は中央権力の影響下にあり、自由に発行することが難しい

では、これらのアンチテーゼとしてのトークンをICPで実装します。

前提知識: ICPとEthereumの比較

一旦、ICPについて軽く触れておきます。
個人的にICPの概要を把握するためのおすすめのアプローチがEthereumと対比させることです。

基本的にEthereumは金融システムを構築するための技術です。
一方、ICPは非金融領域への応用が意識された意欲的な設計です。
大雑把に言えばICPは「Ethereumより開発自由度が高いブロックチェーン」です。
従来のブロックチェーンの制約を克服し、より汎用的なWebアプリケーション基盤として機能します。

項目 Ethereum Internet Computer
実行環境 ・EVMで単一スレッド実行
・同期処理のみ対応
・スマートコントラクトはブロックチェーン上に展開
・WAMSで並列実行が可能
・非同期処理に対応
・Canisterはチェーン外で実行
ストレージ ・オンチェーンストレージは高コスト
・外部ストレージ(IPFS等)との連携が必要
・Canisterで最大8GBまでのストレージ機能
・アプリケーションデータを直接保存可能
開発言語 ・Solidity主体
・EVM互換言語に限定
・Motoko, Rust等
・WASM対応言語であれば利用可能
ガス代 ・ユーザーが都度支払い
・価格変動の影響を受けやすい
・事前にCanisterにデポジット(Reverse Gas)
・ユーザーは支払い不要
スケーラビリティ ・単一チェーンでの処理
・L2ソリューションが必要
・サブネットによる並列処理
・ネイティブでスケーリング可能
ユースケース ・金融取引(DeFi)が主流
・トークン標準規格が確立
・非金融系アプリケーションに適合
・フロントエンドのホスティングも可能
ファイナリティ ・複数ブロックの承認待ちが必要 ・サブネットによる高速なファイナリティ

ICPで地域通貨を実装する10のアイディア

「ICPで地域通貨を実装する10のアイディア」について、それぞれ詳しく解説します。

1. デジタルネイティブなトークン設計

まず、完全なデジタルネイティブトークンとして設計することで、物理的な制約から解放されます。
特に、ICPのCanister上で実装するトークンは、金融システム構築基盤として設計されたEVMより柔軟で、高い表現力を持ちます。

WebAssemblyベースの実装により、以下のような特徴を持つことができます。

  • リアルタイムでの価値変動や条件付きの取引の実装
  • 複数の価値尺度の同時管理
  • プログラマブルな価値交換ルールの設定
  • スマートコントラクトとの連携による自動執行
  • デジタルアイデンティティとの統合

このアプローチにより、物理的な通貨では不可能だった新しい経済的インセンティブの設計が可能になります。

2. 老化するトークン

ミヒャエル・エンデの「老化する通貨」(Aging Money)という概念をCanisterで表現します。
時間経過に応じて自動的に価値が減少していく仕組みをCanisterで実装し、例えば1日あたり1%ずつ価値が減少するよう設定します。
この減少率はコミュニティのガバナンスによって調整可能で、経済活動の活性化を促します。

  • 保有期間に応じた価値の自動減少
  • コミュニティによる減少率の動的調整
  • 価値減少分の再分配メカニズム
  • 使用頻度に応じた価値維持ボーナス
  • 季節性を考慮した変動率の実装

この仕組みにより、トークンの貯め込みを抑制し、活発な経済活動を促進します。

3. 送金時にコミュニケーション必須のトークン

トークン送金時にはメッセージの送信を必須とします。
価値交換にコミュニケーションを必須とする機能は、単なる取引を超えた関係性の構築を促します。
価値交換にコミュニケーションを組み込むことで、取引に意味と文脈を付与します。

  • メッセージ添付必須の送金システム
  • 取引目的や背景の記録
  • コミュニケーション履歴の可視化
  • メッセージの種類に応じたインセンティブ設計
  • コミュニティフィードバックシステムの統合

これにより、単なる価値交換を超えた、意味のある経済活動を促進します。

4. 任意通用力トークン

強制通用力に代わり、任意通用力を導入します。
送金が成立するには、受け取り手側の同意が必要です。
トークンの受け取り時には、添付されたメッセージを確認した上で、受け取りの承認または拒否を選択できます。
強制的な受け取りを排除し、双方向の合意に基づく取引を実現します。

  • 受取承認システム
  • 取引条件の事前合意メカニズム
  • 取引目的の明確化要件
  • 受取拒否権の保護
  • 取引履歴の透明性確保

これにより、より主体的で意味のある経済活動を促進します。

5. 資産性を付与しないトークン

トークンに資産性を付与しません。
例えば他のトークンと交換することで実質的に資産性がある状態になってしまうので、ICP上のDEX(Sonic、ICPSwap、Helix Marketsなど)でのスワップをコントラクト単位で制限します。

投機的な利用を抑制し、実体経済での利用に焦点を当てます。

  • DEXでの取引制限
  • 交換可能性の制限
  • 有効期限の設定
  • 使用目的の制限
  • 価値安定性の確保

支払いや取引以外のトークンのユーティリティを模索し、投機ではなく実際の経済活動に焦点を当てた通貨システムを構築します。

6. 柔軟な価値測定システム

単一の価値尺度を超えた、多次元的な価値評価システムを実装します。

  • 複数の価値指標の統合
  • コミュニティ定義の評価基準
  • 文脈依存的な価値計算
  • 社会的インパクトの定量化
  • 多様な価値観の包含

これにより、多様な価値観を包含した経済圏の形成が可能になります。

7. 累計流通量評価

ユーザーをトークンの現保有量(現在という点)ではなく累計流通量(過去から現在への線)に基づき評価します。

  • 取引頻度の測定
  • 経済活動への貢献度評価
  • 循環速度の可視化
  • 活動履歴の分析
  • コミュニティ貢献の定量化

これにより、コミュニティへの貢献度や経済活動の活性化度を可視化し、持続的な価値循環を促進します。
「お金持ち」の地位が低下し、より公平な価値評価を実現します。

8. 完全なトレーサビリティ

完全なトレーサビリティの実現のため、すべての取引履歴がブロックチェーン上で公開されます。

  • 取引履歴の完全記録
  • プライバシー保護機能
  • 選択的情報開示
  • 監査可能性の確保
  • 不正利用の防止

これにより、透明な経済圏を形成します。

9. 分散型ガバナンス

分散型ガバナンスシステムにより、トークンの運営をコミュニティ主導で行います。
パラメータの調整やルールの変更は、提案と投票のプロセスを経て実施されます。
ICPのネイティブなDAO機能を活用し、透明性の高い運営を実現します。

  • 提案と投票システム
  • パラメータ調整の分散化
  • 透明性の高い意思決定プロセス
  • インセンティブ設計の共同決定
  • ガバナンストークンの活用

これにより、持続可能で民主的な通貨システムを実現します。

10. Sandbox的なサブネット作成

法規制に対応可能な独立したネットワークを構築します。
ICPはメインネット上でサブネットを分けて運用する機能を持っているため、この方法なら日本特有の厳格な法規制をクリアできる可能性があります。

  • 地域固有の規制対応
  • カスタマイズ可能なルール設定
  • スケーラビリティの確保
  • セキュリティの強化
  • 運用の柔軟性

これにより、各地域の要件に適合したシステムを構築できます。

実装例

上記の10のアイディアをCanister上で表現する実装例を二つに分けて紹介します。

老化するトークン(Aging Money )

このトークンは時間経過とともに価値が減少する特徴を持ちます。

  • aging_rate: 1日あたりの価値減少率を定義(例:1% = 100)
  • get_balance(): 実質的な残高を計算。最後の更新時からの経過時間に基づいて価値減少を計算
  • transfer(): 送金時に実質残高をチェックし、新しい残高を更新
  • update_aging_rate(): ガバナンスによる老化率の調整機能

サンプルコードは下記です。

use candid::{CandidType, Principal};
use ic_cdk::api::time;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(CandidType, Serialize, Deserialize, Default)]
pub struct AgingToken {
    // トークンの残高管理
    balances: HashMap<Principal, u64>,
    // 各アカウントの最後の更新時刻
    last_updates: HashMap<Principal, u64>,
    // 1日あたりの価値減少率 (1% = 100)
    aging_rate: u64,
}

impl AgingToken {
    pub fn new(aging_rate: u64) -> Self {
        Self {
            aging_rate,
            ..Default::default()
        }
    }

    // 現在の実質残高を計算
    pub fn get_balance(&self, account: &Principal) -> u64 {
        let raw_balance = self.balances.get(account).copied().unwrap_or(0);
        let last_update = self.last_updates.get(account).copied().unwrap_or(time());
        
        let days_passed = (time() - last_update) / (24 * 60 * 60 * 1_000_000_000);
        let decay_factor = (10000 - self.aging_rate).pow(days_passed as u32);
        
        raw_balance * decay_factor / 10000_u64.pow(days_passed as u32)
    }

    // トークンの転送処理
    pub fn transfer(&mut self, from: Principal, to: Principal, amount: u64) -> Result<(), String> {
        // 送金元の現在の実質残高を確認
        let current_balance = self.get_balance(&from);
        if current_balance < amount {
            return Err("Insufficient balance".to_string());
        }

        // 残高を更新
        self.update_balance(from, current_balance - amount);
        self.update_balance(to, self.get_balance(&to) + amount);

        Ok(())
    }

    // 残高と最終更新時刻を更新
    fn update_balance(&mut self, account: Principal, new_balance: u64) {
        self.balances.insert(account, new_balance);
        self.last_updates.insert(account, time());
    }

    // ガバナンスによる老化率の更新
    pub fn update_aging_rate(&mut self, new_rate: u64) -> Result<(), String> {
        if new_rate > 10000 {
            return Err("Invalid aging rate".to_string());
        }
        self.aging_rate = new_rate;
        Ok(())
    }
}

メッセージ必須のトークン (MessagingToken)

このトークンは送金時にメッセージを必須とし、受取人の承認を必要とします。

  • request_transfer(): メッセージ付きの送金リクエストを作成
  • approve_transfer(): 受取人による送金の承認処理
  • reject_transfer(): 受取人による送金の拒否処理
  • 送金履歴の保持と照会機能

これらの実装は以下の特徴を持ちます:

  • 透明性: すべての取引はブロックチェーン上で追跡可能
  • コミュニケーション: 価値交換に社会的な文脈を付与
  • コミュニティ制御: パラメータはガバナンスにより調整可能
  • 価値の循環促進: 保有よりも使用を促す設計

サンプルコードは下記です。

use candid::{CandidType, Principal};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(CandidType, Serialize, Deserialize, Clone)]
pub struct Transfer {
    from: Principal,
    to: Principal,
    amount: u64,
    message: String,
    timestamp: u64,
}

#[derive(CandidType, Serialize, Deserialize, Default)]
pub struct MessagingToken {
    // トークンの残高管理
    balances: HashMap<Principal, u64>,
    // 承認待ちの送金
    pending_transfers: Vec<Transfer>,
    // 送金履歴
    transfer_history: Vec<Transfer>,
}

impl MessagingToken {
    // 送金リクエストの作成
    pub fn request_transfer(&mut self, from: Principal, to: Principal, amount: u64, message: String) -> Result<(), String> {
        // メッセージは必須
        if message.trim().is_empty() {
            return Err("Message is required for transfer".to_string());
        }

        // 残高チェック
        let balance = self.balances.get(&from).copied().unwrap_or(0);
        if balance < amount {
            return Err("Insufficient balance".to_string());
        }

        // 送金リクエストを作成
        let transfer = Transfer {
            from,
            to,
            amount,
            message,
            timestamp: ic_cdk::api::time(),
        };

        self.pending_transfers.push(transfer);
        Ok(())
    }

    // 送金の承認
    pub fn approve_transfer(&mut self, to: Principal, transfer_index: usize) -> Result<(), String> {
        let transfer = self.pending_transfers.get(transfer_index)
            .ok_or("Transfer not found")?;

        // 受取人のみが承認可能
        if transfer.to != to {
            return Err("Only recipient can approve transfer".to_string());
        }

        // 残高を更新
        let from_balance = self.balances.get(&transfer.from).copied().unwrap_or(0);
        if from_balance < transfer.amount {
            return Err("Insufficient balance".to_string());
        }

        self.balances.insert(transfer.from, from_balance - transfer.amount);
        let to_balance = self.balances.get(&transfer.to).copied().unwrap_or(0);
        self.balances.insert(transfer.to, to_balance + transfer.amount);

        // 履歴に追加
        let completed_transfer = self.pending_transfers.remove(transfer_index);
        self.transfer_history.push(completed_transfer);

        Ok(())
    }

    // 送金の拒否
    pub fn reject_transfer(&mut self, to: Principal, transfer_index: usize) -> Result<(), String> {
        let transfer = self.pending_transfers.get(transfer_index)
            .ok_or("Transfer not found")?;

        if transfer.to != to {
            return Err("Only recipient can reject transfer".to_string());
        }

        self.pending_transfers.remove(transfer_index);
        Ok(())
    }

    // 承認待ちの送金リストを取得
    pub fn get_pending_transfers(&self, account: Principal) -> Vec<Transfer> {
        self.pending_transfers.iter()
            .filter(|t| t.to == account)
            .cloned()
            .collect()
    }

    // 送金履歴を取得
    pub fn get_transfer_history(&self, account: Principal) -> Vec<Transfer> {
        self.transfer_history.iter()
            .filter(|t| t.from == account || t.to == account)
            .cloned()
            .collect()
    }
}

今後の展望

今後の展望として下記などを考えています。

  • アプリケーション全体の設計や、プロジェクトの解像度を高める
  • トークンのスマートコントラクト(Canister)のv1を開発する
  • 地方自治体や大学と提携し、実際にトークンを発行・流通させる実証実験を行う
  • プロジェクトを持続させるための資金を確保する
    • 地方自治体の公的な補助金を申請
    • チェーンやプロトコルのグラント獲得(ICP Developer Grantなど)

参考文献

ICP

お金の研究

Discussion