1. 程式人生 > 其它 >【阿菜用工具】利用 Web3.js 在 ganache 上部署以及呼叫智慧合約

【阿菜用工具】利用 Web3.js 在 ganache 上部署以及呼叫智慧合約

合約部署

要部署的合約

pragma solidity ^0.4.23;
contract  test  {
    uint256 value;
    
    function setValue(uint256 _value) public{
         value = _value;
    }
    
    function getValue() public returns (uint256){
        return value;
    }
    
    function () public payable{
        
    }
}

獲取合約的ABI和bytecode

合約ABI

[
    {
      "payable": true,
      "stateMutability": "payable",
      "type": "fallback"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "_value",
          "type": "uint256"
        }
      ],
      "name": "setValue",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "getValue",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    }
]

合約bytecode

// add '0x' in front of the bytecode
0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632096525514604b57806355241077146073575b005b348015605657600080fd5b50605d609d565b6040518082815260200191505060405180910390f35b348015607e57600080fd5b50609b6004803603810190808035906020019092919050505060a6565b005b60008054905090565b80600081905550505600a165627a7a72305820437e5b6f23c9e202f4188fde72ebdd65de3a5c7fca347bea516a2f576748a9240029

部署程式碼

const Web3 = require('web3')
// RPC SERVER
const web3 = new Web3('http://localhost:7545')
var Tx     = require('ethereumjs-tx').Transaction

// your account and private key
const account = '0x1275270073b7CA41Cd1a62736795f80f7b52487c'
const pk1 = '56a0717cbc04b0e47732d5be497ad57052594c03088b9ef889fefca107ffeecb'
const private_key = Buffer.from(pk1, 'hex')

// get the nonce of account
web3.eth.getTransactionCount(account, (err, txCount) => {
	
	// the bytecode of contract
  const data = "0x608060405234801561001057600080fd5b5060dc8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632096525514604b57806355241077146073575b005b348015605657600080fd5b50605d609d565b6040518082815260200191505060405180910390f35b348015607e57600080fd5b50609b6004803603810190808035906020019092919050505060a6565b005b60008054905090565b80600081905550505600a165627a7a72305820437e5b6f23c9e202f4188fde72ebdd65de3a5c7fca347bea516a2f576748a9240029"

  // set transaction object
  const txObject = {
    nonce:    web3.utils.toHex(txCount),
    gasLimit: web3.utils.toHex(6721975),
    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
    data: data
  }

  // sign transaction
  const tx = new Tx(txObject)
  tx.sign(private_key)

  const serializedTx = tx.serialize()
  const raw = '0x' + serializedTx.toString('hex')

  // send transaction
  web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('txHash:', txHash)
  })
})

執行結果


注意一個問題,和利用 truffle 部署的智慧合約不同,直接用 Web3.js 部署的合約是不會顯示在 ganache 的 Contract頁面裡的,也就是說,它存在,只是沒顯示。

合約呼叫

呼叫程式碼

var Tx     = require('ethereumjs-tx').Transaction
// search their github for the detail of usage of 'Common' class
const Common = require('ethereumjs-common').default
const Web3 = require('web3')
const web3 = new Web3('http://localhost:7545')

const account = '0x1275270073b7CA41Cd1a62736795f80f7b52487c'
const pk1 = '56a0717cbc04b0e47732d5be497ad57052594c03088b9ef889fefca107ffeecb'
const private_key = Buffer.from(pk1, 'hex')

const contractAddress = '0x6F20B2F0149A680116411a01d5Bc6D4B09E869F4'
const contractABI = [
    {
      "payable": true,
      "stateMutability": "payable",
      "type": "fallback"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "_value",
          "type": "uint256"
        }
      ],
      "name": "setValue",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "getValue",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ]

// initialize the contract object
const contract = new web3.eth.Contract(contractABI, contractAddress)

// call the setValue() function with parameter 123
const calldateABI = contract.methods.setValue(123).encodeABI()

// All of these network's params are the same than mainnets', except for name, chainId, and
// networkId, so we use the Common.forCustomChain method.
const customCommon = Common.forCustomChain(
  'mainnet',
  {
		// set the parameter as your ganache
    name: 'my-network',
    networkId: 5777,
    chainId: 1337,
  },
  'petersburg',
)

web3.eth.getTransactionCount(account, (err, count) => {
	const txObject = {
	    nonce:    web3.utils.toHex(count),
			// set the gas limit as same as of ganache's
	    gasLimit: web3.utils.toHex(6721975),
	    gasPrice: web3.utils.toHex(web3.utils.toWei('10', 'gwei')),
	    to: contractAddress,
		// contract.methods.<function name>(<parameter>).encodeABI()
	    data: contract.methods.setValue(123).encodeABI()
		}
		
	// We pass our custom Common object whenever we create a transaction
	const transaction = new Tx(txObject, { common: customCommon },)
	console.log('transaction:', transaction)
	
	// sign the transaction
	transaction.sign(private_key)
	console.log('transaction.sign:', transaction)
	
	// returns the rlp encoding of the transaction
	const serializedTx = transaction.serialize()
	const raw = '0x' + serializedTx.toString('hex')
	
	web3.eth.sendSignedTransaction(raw, (err, txHash) => {
    console.log('txHash:', txHash)
	if(err){
	    throw err;
		}
	})
})

執行結果

參考文章

  1. 奇客谷:web3.js 教程
  2. 關於ethereumjs-tx在私鏈部署
  3. ethereumjs-common 呼叫方法