バグ修正や機能追加のことを考えると、大きく複雑なプログラムになればなるほど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
は、ガバナンストークンによる投票やプロポーサルの管理、更新フローの管理などを行なっています。具体的には、
- プロポーサルの登録
- 投票
- トランザクションの実行
つまり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
というファンクションがあります。コントラクト更新は、これらのファンクションを用いて下記のように実行されます。
_setPendingImplementation
ファンクションを呼び出し新しい実装コントラクトのアドレスを登録する。_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.sol
やGovernance.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
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/
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/
最新記事 by Akihiro Tanaka (全て見る)
- Euler Financeハッキング事件はなぜ起きたのか - 2023-04-19
- Upgradeableなスマートコントラクトは分散化していると言えるのか - 2022-12-01
- ERC1167(Minimal Proxy Contract)で実装するERC20のFacrotyコントラクト - 2020-01-02