天天看點

如何編寫智能合約之一:智能合約編寫、編譯以及部署

開發環境配置

  1. 安裝

    truffle

    . 在指令行下執行(已經有npm環境)
MacBook-Pro:~  zhi$ npm install -g truffle
/usr/local/bin/truffle -> /usr/local/lib/node_modules/truffle/build/cli.bundled.js
/usr/local/lib
└── [email protected] 
           

使用

truffle

指令檢視版本資訊

MacBook-Pro:~  zhi$ truffle version
Truffle v4.. (core: .)
Solidity v. (solc-js)
           

使用

truffle

初始化一個測試項目

MacBook-Pro:~  zhi$ mkdir -p ~/Ethereum/demo1
MacBook-Pro:~  zhi$ cd ~/Ethereum/demo1
MacBook-Pro:~  zhi$ truffle init
Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!

Commands:

  Compile:        truffle compile
  Migrate:        truffle migrate
  Test contracts: truffle test
           

初始化之後,所在檔案夾下會建立一些檔案夾以及檔案:

|—contracts 用于存放合約的檔案夾,我們添加的合約都放在這裡

|—migrations 指導合約編譯的檔案

|————-1_initial_migration.js

|————-2_initial_hello.js

|—test 測試目錄

|—truffle-config.js 配置檔案

|—truffle.js

  1. 建立

    Hello.sol

    合約檔案,并儲存在

    truffle

    初始化後的

    contracts

    檔案夾中。檔案内容:
pragma solidity ^.18;

contract Hello{

  function test() pure public returns (string){
    return "It is test!";
  }

  function test1() pure public returns (string){
    return "test1!";
  }

  function echo(string s) pure public returns (string){
    return s;
  }

}
           
  1. 進入指令行編譯以及部署操作

    進入truffle指令行,執行

    truffle develop

    指令
MacBook-Pro:~  zhi$ truffle develop
Truffle Develop started at http://localhost:9545/

Accounts:
() 
() 
() 
() 
() 
() 
() 
() 
() 
() 

Private Keys:
() c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
() ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
() 0dbbe8e4ae425a6d2687f1a7e3ba17bc98c673636790f1b8ad91193c05875ef1
() c88b703fb08cbea894b6aeff5a544fb92e78a18e19814cd85da83b71f772aa6c
() c684f0ba1ef5017716adb5d21a053ea8e90277d0868337519f97bede61418
() cbb0e2411a44db63778987b1e22153c086a95eb6b18bdf89de078917abc63
() d052c865f5763aad42add438569276c00d3d88a2d062d36b2bae914d58b8c8
() aa3680d5d48a8283413f7a108367c7299ca73f553735860a87b08f39395618b7
() 0f62d96d6675f32685bbdb8ac13cda7c23436f63efbb9d07700d8669ff12b7c4
() d5366123cb560bb606379f90a0bfd4769eecc0557f1b362dcae9012b548b1e5

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

編譯,執行指令

compile

truffle(develop)> compile
Compiling ./contracts/Hello.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts
           

部署,執行指令

migrate

truffle(develop)> migrate
Using network 'develop'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 
  Migrations: 
Saving successful migration to network...
  ... 
Saving artifacts...
Running migration: 2_initial_migration.js
  Deploying Hello...
  ... 
  Hello: 
Saving successful migration to network...
  ... 
Saving artifacts...
           

如果之前部署過,在執行指令後,可能不是出現上面的資訊,而是出現

Using network 'develop'.

Network up to date.
           

表示的是,合約沒有過期,這次部署沒有成功。此時需要在部署指令後添加一個

reset

參數即可部署成功。完整指令

migrate --reset

  1. 擷取合約執行個體。将合約執行個體指派給

    contract

    變量,執行指令

    Hello.deployed().then(instance => contract = instance)

truffle(develop)> let contract;
undefined
truffle(develop)> Hello.deployed().then(instance => contract = instance)
TruffleContract {
  constructor: 
   { [Function: TruffleContract]
     _static_methods: 
      { setProvider: [Function: setProvider],
        new: [Function: new],
        at: [Function: at],
        deployed: [Function: deployed],
        defaults: [Function: defaults],
        hasNetwork: [Function: hasNetwork],
        isDeployed: [Function: isDeployed],
        detectNetwork: [Function: detectNetwork],
        setNetwork: [Function: setNetwork],
        resetAddress: [Function: resetAddress],
        link: [Function: link],
        clone: [Function: clone],
        addProp: [Function: addProp],
        toJSON: [Function: toJSON] },
     _properties: 
      { contract_name: [Object],
        contractName: [Object],
        abi: [Object],
        network: [Function: network],
        networks: [Function: networks],
        address: [Object],
        links: [Function: links],
        events: [Function: events],
        binary: [Function: binary],
        deployedBinary: [Function: deployedBinary],
        unlinked_binary: [Object],
        bytecode: [Object],
        deployedBytecode: [Object],
        sourceMap: [Object],
        deployedSourceMap: [Object],
        source: [Object],
        sourcePath: [Object],
        ast: [Object],
        compiler: [Object],
        schema_version: [Function: schema_version],
        schemaVersion: [Function: schemaVersion],
        updated_at: [Function: updated_at],
        updatedAt: [Function: updatedAt] },
     _property_values: {},
     _json: 
      { contractName: 'Hello',
        abi: [Object],
        bytecode: '0x6060604052341561000f57600080fd5b6103248061001e6000396000f300606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636b59084d1461005c578063f15da729146100ea578063f8a8fd6d146101c0575b600080fd5b341561006757600080fd5b61006f61024e565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100af578082015181840152602081019050610094565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100f557600080fd5b610145600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610291565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561018557808201518184015260208101905061016a565b50505050905090810190601f1680156101b25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101cb57600080fd5b6101d36102a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102135780820151818401526020810190506101f8565b50505050905090810190601f1680156102405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102566102e4565b6040805190810160405280600881526020017f4e6f207075726521000000000000000000000000000000000000000000000000815250905090565b6102996102e4565b819050919050565b6102a96102e4565b6040805190810160405280600b81526020017f4974206973207465737421000000000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820f8b8cb5819d0882b82e8e56db58138459357c31c23dbb9760f17111a8011b9490029',
        deployedBytecode: '0x606060405260043610610057576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680636b59084d1461005c578063f15da729146100ea578063f8a8fd6d146101c0575b600080fd5b341561006757600080fd5b61006f61024e565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100af578082015181840152602081019050610094565b50505050905090810190601f1680156100dc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100f557600080fd5b610145600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610291565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561018557808201518184015260208101905061016a565b50505050905090810190601f1680156101b25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101cb57600080fd5b6101d36102a1565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102135780820151818401526020810190506101f8565b50505050905090810190601f1680156102405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102566102e4565b6040805190810160405280600881526020017f4e6f207075726521000000000000000000000000000000000000000000000000815250905090565b6102996102e4565b819050919050565b6102a96102e4565b6040805190810160405280600b81526020017f4974206973207465737421000000000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820f8b8cb5819d0882b82e8e56db58138459357c31c23dbb9760f17111a8011b9490029',
        sourceMap: '26:249:0:-;;;;;;;;;;;;;;;;;',
        deployedSourceMap: '26:249:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;201:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;45:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:2;8:100;;;99:1;94:3;90;84:5;80:1;75:3;71;64:6;52:2;49:1;45:3;40:15;;8:100;;;12:14;3:109;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124:73:0;162:6;;:::i;:::-;175:17;;;;;;;;;;;;;;;;;;;;124:73;:::o;201:71::-;246:6;;:::i;:::-;266:1;259:8;;201:71;;;:::o;45:75::-;82:6;;:::i;:::-;95:20;;;;;;;;;;;;;;;;;;;;45:75;:::o;26:249::-;;;;;;;;;;;;;;;:::o',
        source: 'pragma solidity ^0.4.18;\n\ncontract Hello{\n\n  function test() pure public returns (string){\n    return "It is test!";\n  }\n\n  function test1() pure public returns (string){\n    return "No pure!";\n  }\n\n  function echo(string s) pure public returns (string){\n    return s;\n  }\n\n}\n',
        sourcePath: '/Users/ zhi/Ethereum/demo1/contracts/Hello.sol',
        ast: [Object],
        compiler: [Object],
        networks: [Object],
        schemaVersion: '1.0.1',
        updatedAt: '2018-01-11T08:33:44.367Z' },
     setProvider: [Function: bound setProvider],
     new: [Function: bound new],
     at: [Function: bound at],
     deployed: [Function: bound deployed],
     defaults: [Function: bound defaults],
     hasNetwork: [Function: bound hasNetwork],
     isDeployed: [Function: bound isDeployed],
     detectNetwork: [Function: bound detectNetwork],
     setNetwork: [Function: bound setNetwork],
     resetAddress: [Function: bound resetAddress],
     link: [Function: bound link],
     clone: [Function: bound clone],
     addProp: [Function: bound addProp],
     toJSON: [Function: bound toJSON],
     web3: 
      Web3 {
        _requestManager: [Object],
        currentProvider: [Object],
        eth: [Object],
        db: [Object],
        shh: [Object],
        net: [Object],
        personal: [Object],
        bzz: [Object],
        settings: [Object],
        version: [Object],
        providers: [Object],
        _extend: [Object] },
     class_defaults: 
      { from: '0x627306090abab3a6e1400e9345bc60c78a8bef57',
        gas: ,
        gasPrice:  },
     currentProvider: 
      HttpProvider {
        host: 'http://localhost:9545/',
        timeout: ,
        user: undefined,
        password: undefined,
        send: [Function],
        sendAsync: [Function],
        _alreadyWrapped: true },
     network_id: '4447' },
  abi: 
   [ { constant: true,
       inputs: [],
       name: 'test1',
       outputs: [Object],
       payable: false,
       stateMutability: 'pure',
       type: 'function' },
     { constant: true,
       inputs: [Object],
       name: 'echo',
       outputs: [Object],
       payable: false,
       stateMutability: 'pure',
       type: 'function' },
     { constant: true,
       inputs: [],
       name: 'test',
       outputs: [Object],
       payable: false,
       stateMutability: 'pure',
       type: 'function' } ],
  contract: 
   Contract {
     _eth: 
      Eth {
        _requestManager: [Object],
        getBalance: [Object],
        getStorageAt: [Object],
        getCode: [Object],
        getBlock: [Object],
        getUncle: [Object],
        getCompilers: [Object],
        getBlockTransactionCount: [Object],
        getBlockUncleCount: [Object],
        getTransaction: [Object],
        getTransactionFromBlock: [Object],
        getTransactionReceipt: [Object],
        getTransactionCount: [Object],
        call: [Object],
        estimateGas: [Object],
        sendRawTransaction: [Object],
        signTransaction: [Object],
        sendTransaction: [Object],
        sign: [Object],
        compile: [Object],
        submitWork: [Object],
        getWork: [Object],
        coinbase: [Getter],
        getCoinbase: [Object],
        mining: [Getter],
        getMining: [Object],
        hashrate: [Getter],
        getHashrate: [Object],
        syncing: [Getter],
        getSyncing: [Object],
        gasPrice: [Getter],
        getGasPrice: [Object],
        accounts: [Getter],
        getAccounts: [Object],
        blockNumber: [Getter],
        getBlockNumber: [Object],
        protocolVersion: [Getter],
        getProtocolVersion: [Object],
        iban: [Object],
        sendIBANTransaction: [Function: bound transfer] },
     transactionHash: null,
     address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
     abi: [ [Object], [Object], [Object] ],
     test1: 
      { [Function: bound ]
        request: [Function: bound ],
        call: [Function: bound ],
        sendTransaction: [Function: bound ],
        estimateGas: [Function: bound ],
        getData: [Function: bound ],
        '': [Circular] },
     echo: 
      { [Function: bound ]
        request: [Function: bound ],
        call: [Function: bound ],
        sendTransaction: [Function: bound ],
        estimateGas: [Function: bound ],
        getData: [Function: bound ],
        string: [Circular] },
     test: 
      { [Function: bound ]
        request: [Function: bound ],
        call: [Function: bound ],
        sendTransaction: [Function: bound ],
        estimateGas: [Function: bound ],
        getData: [Function: bound ],
        '': [Circular] },
     allEvents: [Function: bound ] },
  test1: 
   { [Function]
     call: [Function],
     sendTransaction: [Function],
     request: [Function: bound ],
     estimateGas: [Function] },
  echo: 
   { [Function]
     call: [Function],
     sendTransaction: [Function],
     request: [Function: bound ],
     estimateGas: [Function] },
  test: 
   { [Function]
     call: [Function],
     sendTransaction: [Function],
     request: [Function: bound ],
     estimateGas: [Function] },
  sendTransaction: [Function],
  send: [Function],
  allEvents: [Function: bound ],
  address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
  transactionHash: null }
           

執行了上面指令後,就可以通過

contract

變量來調用合約。要調用合約中的方法隻需要

contract.method()

,比如要調用

Hello

合約中的

test

方法,執行:

truffle(develop)> contract.test();
'It is test!'
           

PS:這裡調用的

test

方法使用

pure

進行了修飾,是以可以直接調用。如果沒有使用

pure

進行修飾,那麼調用這個

test

方法,就隻能通過

call

來調用:

contract.test.call()

到這裡,這個隻能合約就編寫、編譯并部署完成了!

參考:

黎躍春 —— 如何編寫智能合約(Smart Contract)

繼續閱讀