Upgradeableなスマートコントラクトは分散化していると言えるのか

ブロックチェーンやEthereumといえば分散型、非中央集権というイメージですが、最近ではProxyパターンというアーキテクチャを用いてスマートコントラクトをUpgradeable(更新可能)にした一見中央集権のように思えるプロジェクトが増えています。
バグ修正や機能追加のことを考えると、大きく複雑なプログラムになればなるほどUpgradeableであることの必要性は大きくなりますが、それに伴い非中央集権な実装からは離れてしまっているようにもみえます。
そこでDeFi(分散型金融)の代表格であるAave、Compound、Uniswapのそれぞれがどのようなアーキテクチャを採用してスマートコントラクトをUpgradeableにしているのか、そしてどう分散性とのバランスをとっているのかを調べ、果たしてUpgradeableなスマートコントラクトは分散化していると言えるのか考察してみようと思います。


Upgradeable(更新可能)とは?

まず基本として、Ethereumにおいてスマートコントラクトは一度デプロイしたら更新することはできません。
つまりスマートコントラクトはそもそもUpgradeableにすることはできないということになってしまいますが、Proxyパターンというアーキテクチャを導入するとで見かけ上Upgradeableに振る舞うようなスマートコントラクトを作成することができます。

Proxyパターンとは、メインの実装コントラクトとユーザーとの間にProxyコントラクトが存在するパターンのことを言います。
ユーザーはProxyコントラクトにアクセスし、Proxyコントラクトがロジックを含むメインの実装コントラクトに対してトランザクションを転送します。
この実装パターンでは、Proxyコントラクトは変更されず常に同じアドレスとなりますが、Proxyコントラクトが参照する実装コントラクトを別の実装コントラクトに変更することができるため、全体としてUpgradeableなコントラクトになっていると見做せるようになります。
また、Proxy パターンではdelegatecallという仕組みを使うことでデータの格納先はProxyコントラクト、実行されるロジックは実装コントラクトのメソッドという挙動になるため、参照先の実装コントラクトを変更してもコントラクトはデータを失いません。
Proxyパターンについてより詳細に知りたい方は、こちらの記事により詳しくまとめてあるのでご参照ください。
https://qiita.com/biga816/items/b4f745e67588e8da7ed1

AaveのUpgradeability

まずはAaveを調べてみます。
Proxyパターンにはいくつか種類があるのですが、AaveではTransparent ProxyというProxyパターンを採用しています。
このパターンの特徴は、Proxyコントラクトが実装コントラクトの更新処理を持っている点です。
Proxyコントラクト自体はUpgradeableではないため、コントラクト更新時にコントラクト更新処理自体の削除はでません。
そのため、このパターンでコントラクトが一度デプロイされると、デプロイされたコントラクトはずっとUpgradeableなままになります。

ではまず実際のコントラクトを見てみます。
Aaveでは、Openzeppelinを利用してProxyコントラクトを実装しています。
https://github.com/aave/aave-v3-core/blob/master/contracts/protocol/libraries/aave-upgradeability/BaseImmutableAdminUpgradeabilityProxy.sol

Proxyコントラクトには実装コントラクトのアドレスを更新するupgradeToファンクションがあり、Adminのみが実行できるようになっていることが分かります。
次に、AaveのAdminについて調べてみます。
AaveではProxyコントラクトのデプロイや実装の更新を管理するLendingPoolAddressesProvider.solというコントラクトがあります。
(v3だとPoolAddressesProvider.sol)
このコントラクトによってデプロイされたコントラクトのAdminは、このコントラクト自身のアドレスになります。
つまり、Aaveのメインの実装であるPoolコントラクトなどのAdminはLendingPoolAddressesProvider.solということになります。

また、LendingPoolAddressesProvider.solのデプロイや実装の更新を行うメソッドはコントラクトのオーナーのみが実行できるようになっています。
このコントラクトオーナーは、下記の実際にデプロイされているコントラクトを確認してみると、AaveGovernanceV2.solというコントラクトになっていることが分かります。
https://etherscan.io/address/0xb53c1a33016b2dc2ff3653530bff1848a515c8c5#readContract

このAaveGovernanceV2.solは、ガバナンストークンによる投票やプロポーサルの管理、更新フローの管理などを行なっています。
具体的には、

  1. プロポーサルの登録
  2. 投票
  3. トランザクションの実行
となっており、特定のコントラクトを更新する際にもまずはプロポーサルの起票から行われることになっています。
つまりAaveのコントラクトはUpgradeableでありながら開発チームで自由に更新することはできず、コミュニティによって管理されているということにります。

以上のことから、Aaveはガバナンストークンにより権限が分散していると言えるでしょう。

CompoundのUpgradeability

次はCompoundを調べます。
Compoundでは、Transparent ProxyやUUPS Proxyなど一般的なProxyパターンを使用しておらず、独自のUnitroller.solというコントラクトを用いて、Compoundのメインの処理を司るComptroller.solというコントラクトをUpgradeableにしています。 まず、Unitroller.solを見てみます。
https://github.com/compound-finance/compound-protocol/blob/master/contracts/Unitroller.sol

このコントラクトには、_setPendingImplementationというファンクションと_acceptImplementationというファンクションがあります。
コントラクト更新は、これらのファンクションを用いて下記のように実行されます。

  1. _setPendingImplementationファンクションを呼び出し新しい実装コントラクトのアドレスを登録する。
  2. _acceptImplementationファンクションを呼び出し、上記1で登録された実装コントラクトでComptroller.solを更新する。
またそれぞれのファンクションで実行できるユーザーが制限されており、_setPendingImplementationファンクションはコントラクト内に登録されたAdmin、_acceptImplementationファンクションはComptroller.sol自身のみが実行できるように制御されています。

ここで一つ特徴的なのが、_acceptImplementationファンクションを呼び出すのが実装コントラクトであるComptroller.solである点です。
これは更新される側のコントラクトにコントラクトの更新処理が存在していることことなので、コントラクト更新処理もUpgradeableの対象になっていることになります。
そのため、将来的には実装コントラクト更新時にコントラクトを更新する処理を削除し、自分自身をUpgradeableではないコントラクトにすることもできます。
そのためCompoundのこの独自実装は、下図のUUPS Proxyパターンと同様の特徴を持っているといえます。
次に_setPendingImplementationファンクションを実行できるAdminについて調べてみます。
EtherscanでComptroller.solを確認してみると、AdminはTimelock.solというコントラクトになっていることが分かります。
https://etherscan.io/address/0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B#readContract

Timelock.solは、Governance.solコントラクトで提案、承認された変更をキューに入れて管理したり実行したりするコントラクトです。
そのため、現在の CompoundのコントラクトはUpgradeableでありながらも、更新のフローはGovernance.solにて管理されており、Aaveと同じくガバナンストークンにより権限が分散していると言えそうです。

UniswapのUpgradeability

最後に、Uniswapを調べます。
UiswapではUNIというガバナンストークンが存在します。
そしてこのガバナンストークンはCompoundよりフォークしたTimelock.solGovernance.solなどのコントラクトを使用しているため、Compoundと同じアーキテクチャを用いて管理権限が分散化しています。
https://github.com/Uniswap/governance

しかしUniswapのコントラクト自体はAaveやCompoundのようにUpgradeableになっておらず、分散化された管理権限を用いてもフィーの設定など限定的な設定変更しかできません。
つまり、バグ修正や機能追加を後から実施できない仕様ということです。
そのためUniswapでは、大きくコントラクトが更新される度にV1、V2、V3と別コントラクトとしてデプロイされてきました。

以上ことから、UniswapのコントラクトはUpgradeableでない上にさらにガバナンストークンで権限も分散化しているため、完全に分散化されているアプリケーションであるといえます。

結論

Aave、Compound、Uniswapとそれぞれに共通しているのが、管理権限がガバナンストークンにより分散化している点です。
管理権限が分散化していれば、コントラクトがUpgradableだったとしてもコミュニティによる提案、投票によってのみコントラクトが更新されることがプログラム的に完全に担保されるため、Upgradableなコントラクトでも分散化しているといえます。

逆にUpgradableでないコントラクトであったとしても、管理権限が分散化していない場合は実装によっては管理者がなんでも実行できてしまうため、コントラクトは分散化しているといえない場合があります。
例えばBCG(ブロックチェーンゲーム)では、パラメーターの調整やアイテムのミントなど管理者が強い権限を持っていることで分散化していないことがあります。

結論としては

Q: Upgradeableなスマートコントラクトは分散化していると言えるのか
A: 管理権限がガバナンストークンなどにより分散化していれば言える

です。
ただし、ブロックチェーンの世界では常に

Don’t Trust. Verify.
です。
ぜひこの記事を信頼することなく自分自身の手で実際のコントラクトを確認し、「Don’t Trust. Verify.」してみてください。

Aave: https://github.com/aave
Compound: https://github.com/compound-finance
Uniswap: https://github.com/Uniswap
The following two tabs change content below.
Akihiro Tanaka

Akihiro Tanaka

Smart Contract Engineer
Since 2009, I have been a software engineer at Accenture for 9 years, managing, designing, and developing many services, mainly web and mobile apps.
In 2013, I met Bitcoin and started to work on blockchain-related development in 2018, developing an entertainment DApp for underground idols, a blockchain analysis tool, and an STO platform.
Currently, I am working as a Smart Contract Engineer at Secured Finance, developing a DeFi product.

WEB: https://tanakas.org/