LoginSignup
29
18

More than 5 years have passed since last update.

Truffle の Migration は何をやっている?

Last updated at Posted at 2017-12-19

Truffleを使ってみて、チュートリアルのままマイグレーション実行しましたが、中に何をやっているかはわからなかったので、すこし調べてみました。

migrateコマンド

  • migrationsディレクトリ配下のスクリプトを実行する
  • 前回の実行が成功だった場合は、それ以降の新しいマイグレーションだけ実行する
  • 新しいマイグレーションがなければ、何もしない
  • --reset オプションで実行し直すことができる

各マイグレーションファイル

  • ファイル名は数値で始まる必要があり、それ以降は説明内容で構わない。
  • ファイル名の数値で実行順番決められるようです。
  • マイグレーションの中でdeployerを使って、デプロイなどを実行できる
  • 1つのマイグレーションファイルの中、複数コントラクトをデプロイできる
deployer.deploy(A);
deployer.deploy(B);
  • Aがデプロイ成功したらBをデプロイする のようなこともできる
deployer.deploy(A).then(function() {
  return deployer.deploy(B, A.address);
});
  • マイグレーション処理の2番目の関数はネットワークであり、正式ネットワークなのか、テストネットワークなのかの情報を取得できる
module.exports = function(deployer, network) {
  // 正式ネットワーク以外の場合、デモデータ導入する
  if (network != "live") {
    deployer.exec("add_demo_data.js");
  }
}
  • コントラクトにパラメータを渡すことももちろんできる
deployer.deploy(A, arg1, arg2, ...);
  • 複数コントラクト一気にデプロイするのもできる
deployer.deploy([
  [A, arg1, arg2, ...],
  B,
  [C, arg1]
]);
  • deployer.linkdeployer.autolink関数もありますが、意味まだ理解できてない。

デフォルトcontracts/Migration.solの処理

pragma solidity ^0.4.17;

contract Migrations {
  address public owner;
  uint public last_completed_migration;

  modifier restricted() {
    if (msg.sender == owner) _;
  }

  function Migrations() public {
    owner = msg.sender;
  }

  function setCompleted(uint completed) public restricted {
    last_completed_migration = completed;
  }

  function upgrade(address new_address) public restricted {
    Migrations upgraded = Migrations(new_address);
    upgraded.setCompleted(last_completed_migration);
  }
}
  • truffle initしたら、自動で生成されたマイグレーションファイルであり、マイグレーションの情報をスマートコントラクト上で管理している
  • setCompleted関数は最後実行したマイグレーションのファイル名の数値部分(かな?)を記
  • upgrade関数の意図は まだ理解できてない @nakajo2015 さんにコメントして頂いて、理解しました。
    • 新しいマイグレーションコントラクトをデプロイした後、古いコントラクトが持っているlast_completed_migrationを新しいマイグレーションコントラクトに設定するように見える
    • だが、Migrations(new_address)は初期化関数であるはずなのに、上記ソースの初期化関数はパラメータがないよね?
    • Migrationsだけで、新しいコントラクトであることを勝手に認識できる?なぜ?
    • Migrations(new_address)は初期化関数を呼び出すのではなく、指定されたアドレスnew_addressからコントラクトを取得し、マイグレーションコントラクトとして使うこと
    • 推測になりますが、アップグレードする流れは下記になるじゃないかと
      • 最初デプロイした後のアドレスはaddress1とする
      • 新しくデプロイした後のアドレスは address2 とする
var old_contract = eth.contract(abi).at(address1)
old_contract.upgrade.sendTransaction(address2)

参考記事

29
18
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
18