【阿菜用工具】利用 Web3.js 在 ganache 上部署以及呼叫智慧合約
阿新 • • 發佈:2021-06-16
合約部署
要部署的合約
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;
}
})
})