Home | 简体中文 | 繁体中文 | 杂文 | 知乎专栏 | Github | OSChina 博客 | 云社区 | 云栖社区 | Facebook | Linkedin | 视频教程 | 打赏(Donations) | About
知乎专栏多维度架构微信号 netkiller-ebook | QQ群:128659835 请注明“读者”

15.3. Truffle 快速入门

15.3.1. Ubuntu 环境

15.3.1.1. 启动开发环境

truffle 自带一个开发环境

			
neo@netkiller ~/ethereum/truffle-project %  truffle develop
Truffle Develop started at http://localhost:9545/

Accounts:
(0) 0x627306090abab3a6e1400e9345bc60c78a8bef57
(1) 0xf17f52151ebef6c7334fad080c5704d77216b732
(2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef
(3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544
(4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2
(5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e
(6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5
(7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5
(8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc
(9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de

Private Keys:
(0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
(1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
(2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1
(3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c
(4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418
(5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63
(6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8
(7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7
(8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4
(9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5

Mnemonic: candy maple cake sugar pudding cream honey rich smooth crumble sweet treat

truffle(develop)> 
			
			
				

truffle develop 的作用于 testrpc 类似。

			
neo@netkiller ~/ethereum/truffle-project % testrpc 
EthereumJS TestRPC v6.0.3 (ganache-core: 2.0.2)

Available Accounts
==================
(0) 0xb5fd43ee8fa5ce1db9a30a25ba385ee3bfc72966
(1) 0xf5a732345734e1f0f49cbadb145a20d1e1a44b95
(2) 0x834fcd8c55fdf21fd14c82e9a1ef5d3636a2fed6
(3) 0x5aa4d047d85727309d3ca653c83c3bb0ecd18903
(4) 0xb4db2dede86f4539e56ac4438f6e36f09c307e46
(5) 0x8da382b1a10ab2f1dc149e19fda228a07c78935c
(6) 0xb290297e89b52713548ff93e5fc23bc3c4183dde
(7) 0x546183289bd4d9d33a3aee0ee663c0729926e583
(8) 0xca58321e442533b7f827e6e8976e1905acd15214
(9) 0xe2c0b336bbb03564204e15a2cb7744564a53efcc

Private Keys
==================
(0) ff32f7a06e2fb26b51a745c1e428c60df92c0f9bb3301b19a5b7e0cdfaae521a
(1) cdbfe40321b6ade8a246748df1c48a738b8a531aee4d1f60a45bfd7f941e0064
(2) 7092117c2d7832980945e18645a60a1ed0e59261d040749f8b5202c2fc653d74
(3) f329657c9ad808e9f794a7462a1a9c276266343d5ced263ab618b6a19d6857c1
(4) 1221766592618add3a57ab109f00efcc70867dd8a9b10a0f7ea75c2b619edfc3
(5) c27005d6c3581193124c84766cc0b1cc318cb201b7d00b1035f4a4c7767ba790
(6) 6b7f43dca1dcc00203b751191096bb0602e17a9a94dcee8b846329efa703cea9
(7) 41be5971d71935bc88c3cf8aefd78ed3188c8721b7134cda3b25d353faf05d4f
(8) bd4c9d512a4f2da2cdcd9e4f89c049e3e7ac81bf57a05369997c2f13e793bebb
(9) 04196d803f743cc1fd021e7d02d5a552f14ab9826ccd4d4b265ff96c45169d2c

HD Wallet
==================
Mnemonic:      confirm shift cable melody caught swing erode language spend victory conduct van
Base HD Path:  m/44'/60'/0'/0/{account_index}

Listening on localhost:8545			
			
				

15.3.1.2. 创建项目

			
cd ~/ethereum
mkdir truffle-project
cd truffle-project 
truffle init			
			
				

操作演示

			
neo@netkiller ~/ethereum/truffle-project % truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!

Commands:

  Compile:        truffle compile
  Migrate:        truffle migrate
  Test contracts: truffle test
  
neo@netkiller ~/ethereum/truffle-project % tree 
.
|-- contracts
|   `-- Migrations.sol
|-- migrations
|   `-- 1_initial_migration.js
|-- test
|-- truffle-config.js
`-- truffle.js

3 directories, 4 files			
			
				

目录结构简单说明如下:



contract/ - Truffle默认的合约文件存放地址。
migrations/ - 存放发布脚本文件
test/ - 用来测试应用和合约的测试文件
truffle.js - Truffle的配置文件

app/ - 需要用户创建,应用文件运行的默认目录。

15.3.1.3. 创建合约

			
pragma solidity ^0.4.18;

contract Netkiller {
    string name;
    int num;
    function Netkiller() public{
        name = "default";
        num = 1;
    }
    function setName(string _name) public{
        name = _name;
    }
    function getName() public view returns(string){
        return name;
    }
    function setNum(int n) public{
        num = n;
    }
    function addNum(int m) public view returns(int res){
        res = m + num;
    }
}

			
				
			
neo@netkiller ~/ethereum/truffle-project % vim migrations/2_initial_migration.js

var Netkiller = artifacts.require("./Netkiller.sol");

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

15.3.1.4. 配置 Truffle

打开文件 truffle.js

			
module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
};			
			
				

修改为

			
module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
			
  networks: {
    development: {
      host: "localhost",
      port: 9545,
      network_id: "*" // Match any network id
    }
  }	
  		
};	
			
				

15.3.1.5. 编译智能合约

			
neo@netkiller ~/ethereum/truffle-project % truffle compile
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/Netkiller.sol...
Writing artifacts to ./build/contracts
			
				

truffle默认只会编译最后一次修改过的合约文件, 这是为了减少比重复编译。"--all"选项,可以强制编译所有文件。

编译结果

			
neo@netkiller ~/ethereum/truffle-project % find build 
build
build/contracts
build/contracts/Migrations.json
build/contracts/Netkiller.json
			
				

15.3.1.6. migrate

			
neo@netkiller ~/ethereum/truffle-project % truffle migrate      
Using network 'development'.

Network up to date.			
			
				

15.3.2. Mac 环境

Mac 环境

		
neo@MacBook-Pro ~/ethereum/truffle % node --version
v9.5.0
		
neo@MacBook-Pro ~/ethereum/truffle % npm version
{ npm: '5.6.0',
  ares: '1.13.0',
  cldr: '32.0.1',
  http_parser: '2.7.0',
  icu: '60.2',
  modules: '59',
  napi: '2',
  nghttp2: '1.29.0',
  node: '9.5.0',
  openssl: '1.0.2n',
  tz: '2017c',
  unicode: '10.0',
  uv: '1.19.1',
  v8: '6.2.414.46-node.18',
  zlib: '1.2.11' }		
		
neo@MacBook-Pro ~/ethereum/truffle % truffle version
Truffle v4.0.6 (core: 4.0.6)
Solidity v0.4.19 (solc-js)		
		
			

创建项目并初始化

		
mkdir -p ~/ethereum/truffle
cd 	ethereum/truffle
truffle init	
		
			

truffle 自带一个开发环境

		
neo@netkiller ~/ethereum/truffle-project %  truffle develop
Truffle Develop started at http://localhost:9545/

Accounts:
(0) 0x627306090abab3a6e1400e9345bc60c78a8bef57
(1) 0xf17f52151ebef6c7334fad080c5704d77216b732
(2) 0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef
(3) 0x821aea9a577a9b44299b9c15c88cf3087f3b5544
(4) 0x0d1d4e623d10f9fba5db95830f7d3839406c6af2
(5) 0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e
(6) 0x2191ef87e392377ec08e7c08eb105ef5448eced5
(7) 0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5
(8) 0x6330a553fc93768f612722bb8c2ec78ac90b3bbc
(9) 0x5aeda56215b167893e80b4fe645ba6d5bab767de

Private Keys:
(0) c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
(1) ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
(2) 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1
(3) c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c
(4) 388c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418
(5) 659cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63
(6) 82d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8
(7) aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7
(8) 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4
(9) 8d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5

Mnemonic: candy maple cake sugar pudding cream honey rich smooth crumble sweet treat

truffle(develop)> 
			
		
			

创建合约文件 contracts/Greeter.sol

		
pragma solidity ^0.4.20;

contract Greeter         
{
    address creator;     
    string greeting;     

    function Greeter() public   
    {
        creator = msg.sender;
        greeting = "default";
    }

    function greet() constant public returns (string)          
    {
        return greeting;
    }
    
    function setGreeting(string _newgreeting) public 
    {
        greeting = _newgreeting;
    }
       
    function kill() public
    { 
        if (msg.sender == creator)
            selfdestruct(creator);

    }

}		
		
			

创建部署文件 migrations/2_initial_migration.js

		
var Greeter = artifacts.require("./Greeter.sol");

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

打开文件 truffle.js

			
module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
};			
			
			

修改为

			
module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!
			
  networks: {
    development: {
      host: "localhost",
      port: 9545,
      network_id: "*" // Match any network id
    }
  }	
  		
};	
			
			

编译并部署合约

		
neo@MacBook-Pro ~/ethereum/truffle % truffle compile          
Compiling ./contracts/Greeter.sol...
Writing artifacts to ./build/contracts

neo@MacBook-Pro ~/ethereum/truffle % truffle migrate --reset     
Using network 'development'.

Running migration: 1_initial_migration.js
  Replacing Migrations...
  ... 0xddeac9a1c57772df50064f11227fcb5515e54a3e88e15843f5c0bc1b55a0dad7
  Migrations: 0x2c2b9c9a4a25e24b174f26114e8926a9f2128fe4
Saving successful migration to network...
  ... 0x9b51540f5a7d75a8fc920e3e5e4ec66792ba31fd006bd176901f0e6347af2dba
Saving artifacts...
Running migration: 2_initial_migration.js
  Deploying Greeter...
  ... 0x312ead931bbe4b288315317bdf6735ba4fe4f30c20382f085ca27be345819983
  Greeter: 0xfb88de099e13c3ed21f80a7a1e49f8caecf10df6
Saving successful migration to network...
  ... 0x69eaa7ed49cc72426706d54c4f52ba70b742ed6910f1223eb0df5f250b4b8ec3
Saving artifacts...
		
		
			

测试脚本

		
Greeter.deployed().then(instance => console.log(instance.address))
		
var contract;
Greeter.deployed().then(function(instance){contract= instance;});
contract.greet();
contract.setGreeting("http://www.netkiller.cn")
contract.greet();		
		
			

进入控制台,交互执行上面程序

		
neo@MacBook-Pro ~/ethereum/truffle % truffle console
truffle(development)>

truffle(development)> Greeter.deployed().then(instance => console.log(instance.address))
0x82d50ad3c1091866e258fd0f1a7cc9674609d254
undefined
truffle(development)> var contract;
undefined
truffle(development)> Greeter.deployed().then(function(instance){contract= instance;});
undefined
truffle(development)> contract.greet();
'default'
truffle(development)> contract.setGreeting("http://www.netkiller.cn")
{ tx: '0xa5cbfba78c84415517740a482c2bf2208da0c6b0ecabcd5c22db2c85749041c8',
  receipt: 
   { transactionHash: '0xa5cbfba78c84415517740a482c2bf2208da0c6b0ecabcd5c22db2c85749041c8',
     transactionIndex: 0,
     blockHash: '0x557758e0d9b1ef81f41728cb92f43041d009751d5ce5e2e4424f7fb90f52041a',
     blockNumber: 16,
     gasUsed: 34206,
     cumulativeGasUsed: 34206,
     contractAddress: null,
     logs: [],
     status: 1 },
  logs: [] }
truffle(development)> contract.greet();
'http://www.netkiller.cn'
		
			

15.3.3. ERC20 代币部署

15.3.3.1. 合约文件

				
[ethereum@netkiller truffle]$ cat contracts/TokenERC20.sol
pragma solidity ^0.4.20;

contract TokenERC20 {
    address public owner;
    // Public variables of the token
    string public name;
    string public symbol;
    uint8 public decimals = 2;
    // 18 decimals is the strongly suggested default, avoid changing it
    uint256 public totalSupply;

    // This creates an array with all balances
    mapping (address => uint256) public balanceOf;
    mapping (address => mapping (address => uint256)) public allowance;

    // This generates a public event on the blockchain that will notify clients
    event Transfer(address indexed from, address indexed to, uint256 value);

    // This notifies clients about the amount burnt
    event Burn(address indexed from, uint256 value);

    mapping (address => bool) public frozenAccount;
    event FrozenFunds(address target, bool frozen);

    /**
     * Constrctor function
     *
     * Initializes contract with initial supply tokens to the creator of the contract
     */
    function TokenERC20(
        uint256 initialSupply,
        string tokenName,
        string tokenSymbol
    ) public {
        owner = msg.sender;

        totalSupply = initialSupply * 10 ** uint256(decimals);  // Update total supply with the decimal amount
        balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens
        name = tokenName;                                   // Set the name for display purposes
        symbol = tokenSymbol;                               // Set the symbol for display purposes
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    /**
     * Internal transfer, only can be called by this contract
     */
    function _transfer(address _from, address _to, uint _value) internal {
        // Prevent transfer to 0x0 address. Use burn() instead
        require(_to != 0x0);
        // Check if the sender has enough
        require(balanceOf[_from] >= _value);
        // Check for overflows
        require(balanceOf[_to] + _value > balanceOf[_to]);
        // Save this for an assertion in the future
        uint previousBalances = balanceOf[_from] + balanceOf[_to];
        // Subtract from the sender
        balanceOf[_from] -= _value;
        // Add the same to the recipient
        balanceOf[_to] += _value;
        // Asserts are used to use static analysis to find bugs in your code. They should never fail
        assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
    }

    function transfer(address _to, uint256 _value) public {
        require(!frozenAccount[msg.sender]);
        _transfer(msg.sender, _to, _value);
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        require(!frozenAccount[msg.sender]);
        require(_value <= allowance[_from][msg.sender]);     // Check allowance
        allowance[_from][msg.sender] -= _value;
        _transfer(_from, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) public
        returns (bool success) {
        allowance[msg.sender][_spender] = _value;
        return true;
    }

    function approveAndCall(address _spender, uint256 _value)
        public
        returns (bool success) {
        if (approve(_spender, _value)) {
            return true;
        }
    }

    function burn(uint256 _value) onlyOwner public returns (bool success) {
        require(balanceOf[msg.sender] >= _value);   // Check if the sender has enough
        balanceOf[msg.sender] -= _value;            // Subtract from the sender
        totalSupply -= _value;                      // Updates totalSupply
        return true;
    }


    function burnFrom(address _from, uint256 _value) onlyOwner public returns (bool success) {
        require(balanceOf[_from] >= _value);                // Check if the targeted balance is enough
        require(_value <= allowance[_from][msg.sender]);    // Check allowance
        balanceOf[_from] -= _value;                         // Subtract from the targeted balance
        allowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowance
        totalSupply -= _value;                              // Update totalSupply
        return true;
    }


  function transfer(address _to, uint256 _value, bytes _data) public returns (bool) {
    require(_to != address(this));
    transfer(_to, _value);
    require(_to.call(_data));
    return true;
  }

  function transferFrom(address _from, address _to, uint256 _value, bytes _data) public returns (bool) {
    require(_to != address(this));
    transferFrom(_from, _to, _value);
    require(_to.call(_data));
    return true;
  }

  function approve(address _spender, uint256 _value, bytes _data) public returns (bool) {
    require(_spender != address(this));
    approve(_spender, _value);
    require(_spender.call(_data));
    return true;
  }


    function transferOwnership(address _owner) onlyOwner public {
        owner = _owner;
    }
    function mintToken(address target, uint256 mintedAmount) public onlyOwner {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
    }

    function freezeAccount(address target, bool freeze) public onlyOwner {
        frozenAccount[target] = freeze;
    }
}
				
				

15.3.3.2. 部署文件

				
[ethereum@netkiller truffle]$ cat migrations/2_initial_token.js
var TokenERC20 = artifacts.require("./TokenERC20.sol");

module.exports = function(deployer) {
  deployer.deploy(TokenERC20,1200000000,"Netkiller Coin","NKC");
};
				
				

15.3.3.3. 编译部署

				
[ethereum@netkiller truffle]$ truffle compile
Compiling ./contracts/Migrations.sol...
Compiling ./contracts/TokenERC20.sol...
Writing artifacts to ./build/contracts

[ethereum@netkiller truffle]$ truffle migrate
Using network 'development'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0x80746c040d6c6ed8178f90d74356a994fea81516bdd6579d003c433d7a0a0116
  Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0
Saving successful migration to network...
  ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956
Saving artifacts...
Running migration: 2_initial_token.js
  Deploying TokenERC20...
  ... 0xb375b52fe6df9f298828672f3ba3560d7a6f6806ce344e964439d0febc13cb97
  TokenERC20: 0x345ca3e014aaf5dca488057592ee47305d9b3e10
Saving successful migration to network...
  ... 0xf36163615f41ef7ed8f4a8f192149a0bf633fe1a2398ce001bf44c43dc7bdda0
Saving artifacts...
				
				

15.3.3.4. 合约调用

				
[ethereum@netkiller truffle]$ truffle console
truffle(development)> var contract;
undefined
truffle(development)> TokenERC20.deployed().then(function(instance){contract=instance;});
undefined
truffle(development)> contract.symbol.call().then(console.log);
NKC
truffle(development)> contract.name.call().then(console.log);
Netkiller Coin
				
				

15.3.4. 高级ERC20代币合约

15.3.4.1. 部署合约

解锁账号,查看 gas limit 价格

				
[ethereum@netkiller ~]$ geth attach
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.7-stable/linux-amd64/go1.10.2
coinbase: 0x8232ef29d29f46d3621350ab7097604247ed4830
at block: 2863 (Fri, 11 May 2018 17:16:01 CST)
 datadir: /home/ethereum/.ethereum
 modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0

> personal.unlockAccount(eth.accounts[0],"12345678",50000)
true
> web3.eth.getBlock("pending").gasLimit
4712388
> exit
				
				

配置 truffle.js

				
[ethereum@netkiller truffle]$ cat truffle.js
module.exports = {
  // See <http://truffleframework.com/docs/advanced/configuration>
  // to customize your Truffle configuration!

  networks: {
    development: {
      host: "localhost",
      port: 8545,
	  gas: 4712388,
      network_id: "*" // Match any network id
    }
  }

};
				
				
				
[ethereum@netkiller truffle]$ truffle compile
(node:23256) ExperimentalWarning: The fs.promises API is experimental
Compiling ./contracts/NetkillerAdvancedToken.sol...
Writing artifacts to ./build/contracts
				
				
				
[ethereum@netkiller truffle]$ truffle migrate
(node:23456) ExperimentalWarning: The fs.promises API is experimental
Using network 'development'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0xa5937808d9d42dba231738d79d5989e160a2bbc02aa7e8938d0ee71a11eab9a7
  Migrations: 0x0f6d790c0ce6453161ead810246602c601f836e7
Saving successful migration to network...
  ... 0xabd2d76488caa48eac5b9ad5d662b34a8b41acacb5657ff4f78c5c4530913d2b
Saving artifacts...
Running migration: 2_initial_token.js
  Deploying NetkillerAdvancedToken...
  ... 0x190239e85c54aa407ba8dd98357ebabbe2dcab65811f3c4aab7486af27436a09
  NetkillerAdvancedToken: 0xb45bd60c48ea18991a5f25a644682d8cf7572ccf
Saving successful migration to network...
  ... 0x97b9fffef368b2411341d9fed31bd771d0beebe02bde8c19c61a9e0dde0cc773
Saving artifacts...
				
				

15.3.4.2. 控制台检查合约

				
var contract;
NetkillerAdvancedTokenAirDrop.deployed().then(function(instance){contract=instance;});
contract.symbol.call().then(console.log);
contract.name.call().then(console.log);
contract.totalSupply.call().then(console.log);
contract.balanceOf.call(web3.eth.accounts[0]).then(console.log);

				
				
				
	
				
				

15.3.4.3. 测试转账

				
contract.transfer(web3.eth.accounts[1],100).then(function(){contract.balanceOf.call(web3.eth.accounts[1]).then(console.log);});
				
				
				
contract.transferFrom(web3.eth.accounts[0],web3.eth.accounts[1],100).then(function(){contract.balanceOf.call(web3.eth.accounts[1]).then(console.log);});
				
				

15.3.4.4. 锁仓

				
contract.setLock(true);
contract.transfer(web3.eth.accounts[2],100).then(function(){contract.balanceOf.call(web3.eth.accounts[2]).then(console.log);});
				
				
				

演示

				
truffle(development)> contract.setLock(true);
{ tx: '0x6a603ca9456b574224aa97b8bf1d66280fc8509c94253c0037bc5bb71135a667',
  receipt: 
   { transactionHash: '0x6a603ca9456b574224aa97b8bf1d66280fc8509c94253c0037bc5bb71135a667',
     transactionIndex: 0,
     blockHash: '0x4e0893b5ff6b1d85182dca0ceb3c0c2cb750183ff856b7ad2e323ad2a3b55fdc',
     blockNumber: 13,
     gasUsed: 42424,
     cumulativeGasUsed: 42424,
     contractAddress: null,
     logs: [],
     status: 1 },
  logs: [] }
truffle(development)> contract.transfer(web3.eth.accounts[2],100).then(function(){contract.balanceOf.call(web3.eth.accounts[2]).then(console.log);});
Error: VM Exception while processing transaction: revert
    at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:509:1)
    at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:354:1)
    at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/webpack:/~/xhr2/lib/xhr2.js:64:1)
    at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/httpprovider.js:128:1)
    at /usr/local/lib/node_modules/truffle/build/webpack:/~/truffle-provider/wrapper.js:134:1
    at /usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/requestmanager.js:86:1
    at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:38:1)

				
				

解锁后再测试

				
contract.setLock(false);
contract.transfer(web3.eth.accounts[2],100).then(function(){contract.balanceOf.call(web3.eth.accounts[2]).then(console.log);});
				
				
				
truffle(development)> contract.setLock(false);
{ tx: '0x3d4b8d49626c1171ab7160274a9f573bb06999fa7bc33240704199c7905f62fd',
  receipt: 
   { transactionHash: '0x3d4b8d49626c1171ab7160274a9f573bb06999fa7bc33240704199c7905f62fd',
     transactionIndex: 0,
     blockHash: '0x0c78b27d817449b6a3727a13041f1880cbf5466a8b81719f2541c08d59ca5fb3',
     blockNumber: 15,
     gasUsed: 13680,
     cumulativeGasUsed: 13680,
     contractAddress: null,
     logs: [],
     status: 1 },
  logs: [] }
truffle(development)> contract.transfer(web3.eth.accounts[2],100).then(function(){contract.balanceOf.call(web3.eth.accounts[2]).then(console.log);});
undefined
truffle(development)> BigNumber { s: 1, e: 2, c: [ 100 ] }
				
				

15.3.4.5. 测试空投

				
[ethereum@netkiller ~]$ geth account new
INFO [05-11|17:25:49] Maximum peer count                       ETH=25 LES=0 total=25
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {3c1ba8b80b9a8697f2e34194c2a73a93105be23d}
				
				
				
contract.mintAirdropToken(1000000);
contract.totalAirdropSupply.call().then(console.log);
contract.totalSupply.call().then(console.log);
contract.setAirdrop(10);
contract.setAirdropLock(true);
contract.balanceOf.call(web3.eth.accounts[3]).then(console.log);

contract.currentTotalAirdrop.call().then(console.log);
				
				

操作演示

				
[ethereum@netkiller ~]$  truffle console      
truffle(development)> var contract;
NetkillerAdvancedTokenAirDrop.deployed().then(function(instance){contract=instance;});undefined
truffle(development)> NetkillerAdvancedTokenAirDrop.deployed().then(function(instance){contract=instance;});
undefined
truffle(development)> contract.mintAirdropToken(1000000);
{ tx: '0xab251fafc30724273259442fc02bfa429235ff14535f4fb25e29bed7de09ea11',
  receipt: 
   { transactionHash: '0xab251fafc30724273259442fc02bfa429235ff14535f4fb25e29bed7de09ea11',
     transactionIndex: 0,
     blockHash: '0x5498eb579a08e8da1ca2d5ad3d6dd5b0a5c21cc9a630809783d09b65e26929b9',
     blockNumber: 28,
     gasUsed: 47701,
     cumulativeGasUsed: 47701,
     contractAddress: null,
     logs: [],
     status: 1 },
  logs: [] }
truffle(development)> contract.setAirdrop(10);
{ tx: '0xd8a3a16328373858e3cc30c7947b3c3c00db447bb3306f2cf2af58fd0215aef8',
  receipt: 
   { transactionHash: '0xd8a3a16328373858e3cc30c7947b3c3c00db447bb3306f2cf2af58fd0215aef8',
     transactionIndex: 0,
     blockHash: '0x5be96cfd95031a132fc643b06d01dba0b14f736fa9fa3f16dd5bbd9c7f030700',
     blockNumber: 29,
     gasUsed: 42209,
     cumulativeGasUsed: 42209,
     contractAddress: null,
     logs: [],
     status: 1 },
  logs: [] }
truffle(development)> contract.setAirdropLock(true);
{ tx: '0x7b8b5747a64111a500cce22371d78b2c3c4ce0b5a2b585b26c0278876044e231',
  receipt: 
   { transactionHash: '0x7b8b5747a64111a500cce22371d78b2c3c4ce0b5a2b585b26c0278876044e231',
     transactionIndex: 0,
     blockHash: '0xd6960add791b36afac1126a00af16f2833043dcb3416d68bb4056db64313dc93',
     blockNumber: 30,
     gasUsed: 42408,
     cumulativeGasUsed: 42408,
     contractAddress: null,
     logs: [],
     status: 1 },
  logs: [] }
truffle(development)> contract.balanceOf.call(web3.eth.accounts[5]).then(console.log);
BigNumber { s: 1, e: 1, c: [ 10 ] }
undefined