(truffle官翻)第6讲 发布合约

概述

  1. migrations说白了就是将编译好的智能合约移到网上
  2. truffle项目的根目录中,会找到一个名叫migrations目录:
  3. 该目录中都是javascript文件,用于将智能合约发布到以太坊网上
  4. 中文翻译migrate,叫做移植,或者是发布,后面就都这么称呼了
  5. 就是说,需要再该目录下,编辑一些发布文件,这样才能将合约部署到以太坊上

命令

为了运行migrations目录,同样是在项目根目录下,输入如下命令:

1
2
truffle develop  //进入环境(若已经在项目根目录下进入该环境,则不需要执行该命令)
migrate //该环境中发布,migrate可以指定发布网络,网络在truffle.js中:migrate —live

运行后,在migrations中的所有文件都会被执行。
如果你之前已经运行过,则将从上次运行的位置开始执行。
若其中的文件没有改变,则该命令不生效。
可以加入—reset配置,则可覆盖重新运行该命令。

初始化发布

  1. 综述:
    我先大概解释下,要不然后面看的一脸懵逼,按我的理解,就是初始化truffle项目的时候,contracts目录中会自动生成一个叫做Migrations.sol的智能合约文件,然后你需要按照“迁移文件(下面介绍)”的规则实现具体的迁移,其中需要引用到该Migrations.sol中的合约,否则移植功能无法实现。
    下面的内容都是官方的翻译,基本就是我这句话的意思。
  2. Truffle需要你有一个发布合约以便可以使用提供的移植功能。这个合约必须包含一个特殊的接口,但是你按照你的想法任意修改合约。对于大多数项目,这个合约将会作为第一次迁移进行部署,并且不会再被更新。
    另外,这个发布合约在你使用truffle init命令时候,就会被创建出。然后你就可以按着你的想法在里面进行调整了。默认创建的该移植合约如下:
    文件地址:项目根目录/contracts/Migrations.sol
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    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);
    }
    }
  3. 请注意!:
    你必须在你第一次发布时候,部署上面的Migrations合约,这样才能移植功能才能生效。为此,你必须创建一个移植文件,类似如下:
    文件名:migrations/1_initial_migration.js
    1
    2
    3
    4
    5
    6
    var Migrations = artifacts.require("./Migrations.sol");

    module.exports = function(deployer) {
    deployer.deploy(Migrations);
    };

    备注
    1. 文件名需要以数字开头,之后的文件名随意。需要数字编号,才能知道记录迁移是否成功。
    2. artifacts.require(“MyContract”):
      在开始移植前,我们会通过该方法告诉Truffle,我们想和哪个合约进行交互。这个方法类似于nodejs中的require,但是在这里,它可以返回一个合约的抽象层,我们可以在我们发布的其余脚本中使用该合约抽象层。
    3. 注意:传入的MyContract必须是指具体的合约,而不是一个合约文件名(因为一个文中可能有多个合约)。
    4. module.exports:
      所有的迁移必须通过module.exports语法导出一个函数。每个导出的函数必须接受一个deployer对象作为它的第一个参数。该对象提供了一个清晰的语法结构,同时提供了一些通用的职责(比如保存发布的文件,以备稍后使用)
    5. deployer对象是用来缓存发布任务的主要操作接口,这些接口稍后介绍。
  4. 可以依照编号继续创建新的发布

部署

  1. 你的迁移文件被deployer放到部署任务中,,你可以同步编写部署任务,deployer将会按照顺序继续执行:
    1
    2
    deployer.deploy(A);
    deployer.deploy(B);
  2. 或者也可以按照如下方式进行部署
    1
    2
    3
    4
    // Deploy A, then deploy B, passing in A's newly deployed address
    deployer.deploy(A).then(function() {
    return deployer.deploy(B, A.address);
    });

网络考虑

  1. 根据网络条件部署,这是一项高级功能,请先参考:第15讲 网络和app发布
  2. 要考虑网络,则需要按如下编写迁移文件
    1
    2
    3
    4
    5
    6
    7
    module.exports = function(deployer, network) {
    if (network == "live") {
    // Do something specific to the network named "live".
    } else {
    // Perform a different step otherwise.
    }
    }

可用账户

移植文件可以通过客户端或者web3返回一些账户列表如下:

1
2
3
module.exports = function(deployer, network, accounts) {
// Use the accounts within your migrations.
}

API

deployer中包含有很多可以简化移植的功能

  1. deployer.deploy(合同,参数…选项)
    用于部署一个具体的合同,其中涉及到传入一个合约,还有一些特定的参数。这对单例合约是很有用的,在整个dapp中,只会被实例化一次。
  2. 你可以部署一个或者一组合约,以便加速合约的部署。对于第二个参数,可以包含指定的键名(例如:overwrite)或者别的参数(如:gas、from),如果overwrite设置为false,则表示不会覆盖,不执行该合约。
  3. 请注意,在调用deploy部署前,你需要先部署和链接(关于链接,看下一节)好你所依赖的库,
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // Deploy a single contract without constructor arguments
    deployer.deploy(A);

    // Deploy a single contract with constructor arguments
    deployer.deploy(A, arg1, arg2, ...);

    // Don't deploy this contract if it has already been deployed
    deployer.deploy(A, {overwrite: false});

    // Set a maximum amount of gas and `from` address for the deployment
    deployer.deploy(A, {gas: 4612388, from: "0x...."});

    // Deploy multiple contracts, some with arguments and some without.
    // This is quicker than writing three `deployer.deploy()` statements as the deployer
    // can perform the deployment as a single batched request.
    deployer.deploy([
    [A, arg1, arg2, ...],
    B,
    [C, arg1]
    ]);
    // External dependency example:
    //
    // For this example, our dependency provides an address when we're deploying to the
    // live network, but not for any other networks like testing and development.
    // When we're deploying to the live network we want it to use that address, but in
    // testing and development we need to deploy a version of our own. Instead of writing
    // a bunch of conditionals, we can simply use the `overwrite` key.
    deployer.deploy(SomeDependency, {overwrite: false});
  4. deployer.link(library,destinations)用于将一个已经部署的library连接到一个或者多个合约。
    destinations,目的地,可以是一个或者多个合约,如果目的地不含有效的库,则忽略
    1
    2
    3
    4
    5
    6
    7
    // Deploy library LibA, then link LibA to contract B, then deploy B.
    deployer.deploy(LibA);
    deployer.link(LibA, B);
    deployer.deploy(B);

    // Link LibA to many contracts
    deployer.link(LibA, [B, C, D]);
  5. deployer.then(function(){…})
    运行任意一个步骤。在移植过程中使用它来调用特定的合同功能,以添加,编辑和重新组织合同数据。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    var a, b;
    deployer.then(function() {
    // Create a new version of A
    return A.new();
    }).then(function(instance) {
    a = instance;
    // Get the deployed instance of B
    return B.deployed();
    }).then(function(instance) {
    b = instance;
    // Set the new instance of A's address on B via B's setA() function.
    return b.setA(a.address);
    });
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2017-2023 Jason
  • Visitors: | Views:

谢谢打赏~

微信