Skip to main content

原文準拠 Phase 1:基礎

3.3 標準とデザインパターン

Midnight Academy Phase 1 / Unit 3 / 3.3 の原文準拠版。ERC-20 / ERC-721 / ERC-1155 などのトークン標準と、Ownable・アクセス制御・Pull over Push・サーキットブレーカー・Factory といった定番のデザインパターンを正確に。


📘 Academy原文準拠 | Phase 1 · Unit 3 · Lesson 3.3 Smart Contract Standards & Patterns 内容に忠実な日本語版です。原文(英語)・図・動画は公式 Academy(外部リンク・別タブで開きます)を正本に。

スマートコントラクト開発が成熟してくると、コミュニティは「多くの契約は、よく似た問題を解いている」ことに気づきました。

だったら全員が車輪を再発明する必要はありません。そこで開発者たちは、よくあるニーズに対してテスト済みで信頼できる答えになる標準(standards)デザインパターン(design patterns)を整えてきました。

昔は携帯の充電器がメーカーごとにバラバラだったのを覚えていますか。ノキアはこれ、モトローラはあれ、サムスンはまた別。そこに USB が登場して、急にぜんぶ「ただつなぐだけで動く」ようになりました。標準がスマートコントラクトにもたらしたのは、まさにこれと同じことです。

このレッスンでは、もっとも重要な標準(トークン標準など)と、契約をより安全に・効率的に・相互運用可能(interoperable)にする実績あるデザインパターンを見ていきます。

スマートコントラクト標準とは

標準とは、「契約はどう振る舞うべきか」を定めた、みんなで合意したインターフェース/仕様のことです。全員が同じ標準に従うと、別々のアプリどうしがすんなり連携できます。

もし標準が無いと、新しいトークンが出るたびに「どこでも動かすための独自コード」が必要になります。取引所は専用の処理を書かなければならず、ウォレットも更新が必要になり、まさにカオス。(実際、標準が現れる前はそうでした。)

トークン標準

もっとも広く採用されているスマートコントラクト標準は、トークンに関するものです。

ERC-20: 代替可能トークン標準

ERC-20 は、代替可能トークン(fungible token)の標準です。代替可能とは、各単位が同一で交換可能だということ。通貨のようなイメージです。

中心となる関数:

関数 役割
transfer() 別のアドレスへトークンを送る
balanceOf() あるアドレスのトークン残高を調べる
approve() 別のアドレスに、自分のトークンを使うことを許可する
transferFrom() (許可のあと)別のアドレスに代わってトークンを移す

ERC-20 以前は、どのトークンも仕様がバラバラで、取引所は新しいトークンごとに独自コードを書く必要がありました。ERC-20 のおかげで、どんなウォレットや取引所でも、どんな ERC-20 トークンにも自動的に対応できます。

代表的なユースケースは、暗号通貨・ガバナンストークン・リワードポイント・ステーブルコインなどです。

ERC-721: 非代替性トークン(NFT)標準

ERC-721 は、各トークンがユニークで交換不可能なトークンを定義します。

ここが ERC-20 と大きく違うところで、各トークンは固有の IDを持ち、それぞれ別のプロパティやメタデータを持てます。

中心となる関数:

関数 役割
ownerOf(tokenId) この特定のトークンを誰が所有しているか?
transferFrom() 特定のトークンを移す
tokenURI(tokenId) 特定のトークンのメタデータを取得する

このタイプのトークンの代表的なユースケースは、デジタルアート・コレクティブル・不動産の権利証・イベントチケット・ゲームアイテムなどです。

ERC-1155: マルチトークン標準

ERC-1155 は、1つの契約で複数のトークン種別(代替可能・非代替性の両方)を扱えるようにします。これがとても便利なのは、たくさんのトークン種別が必要なゲームやプラットフォームが、種別ごとに別々の契約をデプロイせずに、1つの契約で済ませられるからです。

たとえば、あるゲームではこんな構成が考えられます:

  • ゴールドコイン(代替可能、トークン ID 1)
  • 魔法の剣(非代替性、トークン ID 100〜199)
  • 回復薬(代替可能、トークン ID 2)

ERC-1155 は代替可能トークンも非代替性トークンも1つの契約の中で扱えるので、1つの契約がすべてを管理できます。

よく使うデザインパターン

標準は「どんな関数を含めるべきか」を教えてくれます。パターンは「それらをどう安全に作るか」を教えてくれます。これらはルールではなく、長年の高くついた失敗から得られた苦い知恵です。

Ownable パターン

所有権の制御を付け忘れたせいで資金を抜かれた契約を、数えきれないほど見てきました。多くの契約には、特権的な操作ができる単独の管理者が必要です。Ownable パターンは、owner(所有者)アドレスを1つ定めて、関数へのアクセスを制限する modifier を提供することで、これを解決します。

Ownable パターンはとてもシンプルです:

  • 契約は owner を持つ(ふつうはデプロイした人)
  • 特定の関数は「呼び出しているのは owner か?」をチェックする
  • そうでなければトランザクションは失敗する

いわばマスターキーを持つようなものです。用途はたくさんありますが、いくつか挙げると、契約のアップグレード、緊急停止、設定変更などです。

アクセス制御 / ロールベースのアクセス

「owner か、そうでないか」という単純な区別だけでは足りないことがあります。owner / 非 owner よりも、もっと細かな区別が欲しい場面があるのです。

たとえばこんな役割が欲しいかもしれません:

  • 契約を一時停止できる Admin(管理者)
  • トークンを発行できる Minter
  • アドレスをブラックリスト入りできる Moderator
  • 資金を動かせる Treasurer(出納係)

ロールベースアクセス制御(role-based access control)を使うと、アドレスごとに別々の権限を割り当てられます。セキュリティクリアランスのレベルが何段階もあるようなイメージです。

Pull over Push(引き出しパターン)

複数のアドレスへループで支払いを送ると、1つのアドレスが受け取りを拒否しただけで処理全体が止まり、ほかの全員もブロックされることがあります。そこで、支払いをプッシュ(こちらから送りつける)のではなく、ユーザー自身にプル(自分で引き出す)させます。

悪い方法(push):

良い方法(pull):

この方法だと、失敗が1件ごとに隔離され、ユーザーが自分のガスコストをコントロールでき、攻撃面(attack surface)も小さくなります。

サーキットブレーカー(緊急停止)

稼働中の契約に致命的なバグが見つかったとき、ただちに操作を止める手段が必要です。そこで、問題が解決するまで重要な関数を凍結する一時停止(pause)の仕組みを実装します。

このパターンの主なユースケースは、セキュリティインシデント、メンテナンス、見つかった脆弱性への対応など。見栄えのよい仕組みではありませんが、数百万ドルが危険にさらされたとき、「あって良かった」と思うはずです。

Factory パターン

似たような契約をたくさんデプロイしたい場合(たとえば分散型取引所のトークンペアなど)、どうやりますか。他の契約のインスタンスを生成して追跡する Factory(工場)契約を作ればよいのです。

たとえば Uniswap は、流動性プールの契約を作るために Factory を使っています。1つ1つのプールを手作業でデプロイする代わりに、Factory が必要に応じて生成してくれます。

🖼️ 原文の図:Factory 契約が、複数の同種インスタンス(プール契約など)を生成・管理する様子を示した図があります(本ページでは図は省略)。

標準とパターンの違い

標準とパターンの違いを対比した図。標準(スタンダード)はインターフェースを定義する・相互運用性を確保する(例:ERC-20)、パターン(設計パターン)は設計上の問題を解決する・セキュリティ/効率性を向上させる(例:Ownable=所有権管理)。

  1. 標準(Standards)は、契約がどんな関数を持たなければならないかを教えてくれます。
  2. パターン(Patterns)は、契約のロジックをどう構成するかを教えてくれます。

この2つは一緒に使えます。たとえば、管理用の関数に Ownable パターンを使う ERC-20 トークン(標準)、という組み合わせです。ただし、なぜこれらのパターンがこれほど大事なのか、冷や水を浴びせるような事実もあります。ここに挙げたパターンはすべて、誰かが数百万ドルを失ってその教訓を学んだからこそ存在しています。 DAO ハックが起きたとき、reentrancy guard(再入攻撃ガード)を使っていなかったために 6,000 万ドルが消えました。

アクセス制御の無いラグプル(持ち逃げ)は数知れず。チームが ERC-20 に従わなければ、そのトークンはウォレットに表示されません。独自のパターンを発明すると、監査人は「何をしているのか」を解き明かすために倍の料金を取ります。標準に従わず「賢いやり方」をしようとすると、たいていはお金を失う新しい方法を作っているだけです。

OpenZeppelin のコントラクトは数十億ドルを守っています。Uniswap は新しいトークン標準を作らず、既存のものを創造的に使っただけです。Midnight の上級モジュールに進んでも、同じパターンが、プライバシーを足しただけでそのまま当てはまります。Ownable パターンは依然として存在しますが、今度はowner を隠せるようになります。ゲームは同じ、ルールが新しいだけです。

開発者として押さえる点

  • 標準=何の関数を持つか、パターン=どう安全に組むか。両方を一緒に使う(例:Ownable を使う ERC-20
  • トークン標準は3つを区別:ERC-20(代替可能)/ ERC-721(ユニーク・固有 ID)/ ERC-1155(1契約で両方を扱うマルチトークン)
  • Pull over Push:支払いは「送りつける」より「自分で引き出させる」。失敗を隔離し、ガスもユーザー持ちにでき、攻撃面が減る
  • Ownable / ロールベースアクセス制御で特権操作を守り、サーキットブレーカーで緊急停止できるようにする。付け忘れは資金流出の典型原因
  • パターンは「高くついた失敗の知恵」。独自発明より標準準拠(OpenZeppelin など)が安全で監査も安い
  • Midnight でも同じパターンがそのまま使え、プライバシーが上乗せされる(例:owner を隠せる Ownable)

やさしい版・公式へ

つぎに読むページ

➡️ 原文準拠コースの入口へ戻る。このコースについて(次のレッスンは順次追加します)