Ethereumデベロッパの間ではOpenZeppelin Solidity(旧: Zeppelin Solidity・ALISでもお世話になっている)で有名なZeppelinが新たにZeppelinOSをリリースしました。
ZeppelinOS is an operating system designed specifically for smart contracts. It provides an on-chain set of upgradeable standard libraries, and an incentive structure to continually upgrade and patch itself.
(意訳: ZeppelinOSはスマートコントラクトに特化したOSです。更新可能なコントラクトを作成するための標準ライブラリを含み、スマートコントラクトの継続的なアップグレードを容易にします)
とのこと。
スマートコントラクトの更新の困難さを解決し、一般的なアプリケーションと同様の継続的改善を行うためのソリューションを目指しているようです。
今回はこちらを評価します。
注:スマートコントラクトへの更新機能の付加は常に非中央集権性とのトレードオフを意味することに注意してください。コントラクトに更新機能が無いということは、そのコントラクトが管理者の意思で更新されることはないという非中央集権性をブロックチェーンの改竄耐性を以て担保することを意味します。安易に更新機能を付加すべきではなく、ÐAppsの仕様や方向性とこのトレードオフが持つ意味を充分に理解した上で選択肢の一つとすべきです。
公式の手順に従って準備してゆきます。
まずはZeppelinOSインストール。後で使用するので、まだ入れていない方はganache-cliも入れておきましょう。
npm install --global zos
npm install --global ganache-cli
イニシャライズ。入力を求められた場合はすべてデフォルトのままEnter。
mkdir my-app && cd my-app
npm init
zos init my-app
ZeppelinOSの目玉であろう更新可能ÐAppsの作成を公式の手順に従って試してみます。
ZeppelinOS上でコントラクトを更新可能にするために必要なzos-libをインストール。
npm install zos-lib
MyContract.solをcontractsディレクトリ配下に作成
vi contracts/MyContract.sol
コントラクトの中身は以下の通り。(現状ALISでコード書くのつらい)
import "zos-lib/contracts/migrations/Migratable.sol";
contract MyContract is Migratable {
uint256 public x;
function initialize(uint256 _x) isInitializer("MyContract", "0") public {
x = _x;
}
}
このinitialize関数は標準コンストラクタの代わりに使用するもので、ZeppelinOS上でコントラクトを更新可能とするために必須のものです。
ZeppelinOSにコントラクトを登録します。
zos add MyContract
ganache-cliを起動しておきます。
ganache-cli --port 9545
localネットワークにZeppelinOS管理下のコントラクトをpushします。
zos push --network local
これによりzos.local.jsonが生成され、ZeppelinOSのlocalネットワークでの情報が集約されます。
{
"contracts": {
"MyContract": {
"address": "0x7cfc9712894e470d67b30a6163718c342f2c2cf0",
"bytecodeHash": "dd7dce24b54bbb1e41d3995e806d5988d7769e2060939e8220c252fa74d0e063"
}
},
"proxies": {},
"app": {
"address": "0x74dd87977f1173f8ceb96c55c73d47b73347093e"
},
"version": "0.1.0",
"package": {
"address": "0x85c13b988991db59ed6b2be106f14b4dcfabad32"
},
"provider": {
"address": "0x490ef2c25bfff56f9104784968fe717ccc8c3036"
}
}
更新可能なコントラクトのインスタンス(と公式で呼んでいる)を作成してみましょう。
zos create MyContract --init initialize --args 42 --network local
MyContract.solのinitialize関数の引数に42が渡された状態でデプロイされます。zos.local.jsonも更新されます。
{
"contracts": {
"MyContract": {
"address": "0x7cfc9712894e470d67b30a6163718c342f2c2cf0",
"bytecodeHash": "dd7dce24b54bbb1e41d3995e806d5988d7769e2060939e8220c252fa74d0e063"
}
},
"proxies": {
"MyContract": [
{
"address": "0xb2cebbe4f0b470ea0fda0b95bbe36dd2d4c790f3",
"version": "0.1.0",
"implementation": "0x7cfc9712894e470d67b30a6163718c342f2c2cf0"
}
]
},
"app": {
"address": "0x74dd87977f1173f8ceb96c55c73d47b73347093e"
},
"version": "0.1.0",
"package": {
"address": "0x85c13b988991db59ed6b2be106f14b4dcfabad32"
},
"provider": {
"address": "0x490ef2c25bfff56f9104784968fe717ccc8c3036"
}
}
proxiesにMyContractの情報が登録されていますね。コントラクトを更新可能とするためにProxyPatternsを使用していることがわかります。
MyContractを更新して新しい機能を追加してみましょう。MyContract.solを以下のように書き換えます。
import "zos-lib/contracts/migrations/Migratable.sol";
contract MyContract is Migratable {
uint256 public x;
function initialize(uint256 _x) isInitializer("MyContract", "0") public {
x = _x;
}
function increment() public {
x += 1;
}
}
新しいコードをpushします。
zos push --network local
コントラクトを更新します。
zos upgrade MyContract --network local
動作確認です。your-instance-addressにはzos.local.jsonのproxiesのMyContractのアドレスを入力します。今回の場合は
0xb2cebbe4f0b470ea0fda0b95bbe36dd2d4c790f3となります。
npx truffle console --network=local
truffle(local)> myContract = MyContract.at(<your-instance-address>)
truffle(local)> myContract.increment()
truffle(local)> myContract.x()
43
新しい関数が追加されていることが確認できましたね。ここでは割愛しますが、zos.local.jsonの参照先コントラクトのアドレスが更新されていることも確認しておきましょう。
- Upgradeableなコントラクトの作成・管理が非常に容易。
- Truffleがうまくラップされている
- 未評価の機能や今後の開発次第ではÐApps開発・運用のデファクトスタンダードになるかもしれない
Upgradeableなコントラクトにフォーカスしていますが、その管理を踏まえたÐApps全体の開発・運用の基盤としての可能性を感じました。うまくTruffleに不足しているレイヤーを補完しているように思います。
ZeppelinOSのファーストインプレッションとしては以上です。
この記事はALIS運営メンバーの投稿です。
- この投稿へはトークン配布されません
- この投稿へのいいねはトークン配布の対象になりません
- この投稿は人気記事一覧へ表示されません