カストディアル・ウォレット構築の実装ガイド:冪等スイープと元帳整合性のポイント

暗号資産の交換所や決済サービスを開発する際、避けて通れないのがカストディアル・ウォレット(預かり資産管理)の構築です。ユーザーの入金用アドレスを監視し、届いた資金を安全かつ効率的に回収(スイープ)する仕組みは、システムの信頼性に直結します。

本記事では、Node.jsとethers.jsを用いた堅牢なスイープ機構の設計と、運用の現場で求められるアーキテクチャについて解説します。

1. オンチェーンの事実と元帳を同期させる「冪等性」の重要性

カストディアル・システムの核心は、ブロックチェーン上の「事実」を、自社のデータベースという「元帳」にいかに正確に反映させるかです。ここで重要なのが、同じ処理を何度行っても結果が変わらない「冪等性(べきとうせい)」の確保です。

私の経験上、ネットワークの遅延やAPIのエラーによる「リトライ」は必ず発生します。そのため、デポジットを監視するリスナーと資金を回収するスイーパーを分離し、DBのトランザクションを用いて「一度処理したTxHashは二度と受け付けない」ロジックを徹底する必要があります。

2. ガスコストを40%削減するバッチ処理と運用戦略

ユーザーが入金するたびに即座にスイープを実行すると、送金手数料(ガス代)が嵩み、ビジネスの収益を圧迫します。実際の運用現場では、以下の戦略を組み合わせてコストを最適化します。

  • バッチスイープ:チェーンの混雑状況や蓄積額を見極め、適切なタイミングでまとめて回収する。
  • Hot/Coldの論理分割:出金用の「Hotウォレット」と、資産運用・保管用の「Coldウォレット」を分け、余剰資産をAaveなどで利回り運用(Yield Deployment)に回す。
  • フィーダープロセスの設計:ERC20トークンの回収には、入金アドレス側にガス代(ETHなど)が必要です。これらを自動で補充する仕組みも忘れずに設計しましょう。

3. 現場でハマる「チェーンの再編成(Reorg)」への対策

最も頻発するトラブルの一つが、チェーンの再編成による「確定したはずのトランザクションの消失」です。これを防ぐためには、十分な承認数を待つロジックが不可欠です。

  • ファイナリティの待機:最低でも12ブロック、安全を期すならそれ以上の確認を待ってから元帳に反映させます。
  • DBの整合性確保:残高の更新と処理済みログの作成を、必ずアトミックなトランザクション内で実行します。
async function processDeposit(txHash, userId) {
  const receipt = await provider.getTransactionReceipt(txHash);
  if (!receipt || receipt.confirmations < 12) return;

  const session = await db.startSession();
  session.startTransaction();
  try {
    const alreadyProcessed = await TxLog.findOne({ hash: txHash }).session(session);
    if (!alreadyProcessed) {
      // ユーザー残高の更新とログ記録をセットで行う
      await UserBalance.updateOne({ userId }, { $inc: { balance: receipt.value } }).session(session);
      await TxLog.create([{ hash: txHash, status: 'PROCESSED' }], { session });
    }
    await session.commitTransaction();
  } catch (err) {
    await session.abortTransaction();
  }
}

まとめ:信頼されるインフラを目指して

カストディアル基盤の構築は、単に資金を移動させるだけでなく、「不確実なチェーンの状態」を「確実な内部データ」へと変換する高度な設計が求められます。

冪等性の担保とガス代の最適化を両立させ、スケーラブルで安全なプラットフォームを構築しましょう。

タイトルとURLをコピーしました