使用nodejs部署智能合約
實(shí)現(xiàn)智能合約的方式很多種,可以用truffle框架來實(shí)現(xiàn),編譯,部署。
這里介紹一種簡單的使用nodejs來實(shí)現(xiàn),編譯,部署的方法。
創(chuàng)建一個nodejs項(xiàng)目,實(shí)現(xiàn)一個簡單的智能合約。
mkdir sm && cd sm
npm init
mkdir contracts && cd contracts
vi BaseToken.sol
//BaseToken.sol
contract Token{
address public owner;
mapping (address => uint) public balances;
event Sent(address from, address to, uint amount)
function Token(){
owner = msg.sender;
balances[owner] = 100000000;
}
function send(address receiver, uint amount){
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
}
這個合約實(shí)現(xiàn)了一個造幣和轉(zhuǎn)幣的邏輯。
我們的合約是運(yùn)行在evm上面的字節(jié)碼,solidity是靜態(tài)語言,需要通過編譯器生成evm的字節(jié)碼。
vi compile.js
// compile.js
const fs = require('fs')
const solc = require('solc')
//編譯合約
let source = fs.readFileSync("./contracts/BaseToken.sol", 'utf8')
console.log('compiling contract...');
let compiledContract = solc.compile(source);
console.log('done');
for (let contractName in compiledContract.contracts) {
var bytecode = compiledContract.contracts[contractName].bytecode;
var abi = JSON.parse(compiledContract.contracts[contractName].interface);
}
console.log(bytecode)
調(diào)用node compile.js,對BaseToken進(jìn)行編譯,生成字節(jié)碼。web3中提供了一個部署合約的接口,使用如下,
let gasEstimate = web3.eth.estimateGas({data: '0x' + bytecode});
console.log('gasEstimate: ' + gasEstimate)
let MyContract = web3.eth.contract(abi);
console.log('deploying contract...');
let myContractReturned = MyContract.new([], {
from: address,
data: '0x' + bytecode,
gas: gasEstimate+50000
}, function(err, myContract){
if(!err){
if(!myContract.address){
console.log(`myContract.transactionHash = ${myContract.transactionHash}`);
}else{
console.log(`myContract.address = ${myContract.address}`); // the contract address
global.contractAddress = myContract.address;
}
}else{
console.log(err);
}
});
利用編譯生成的abi和bytecode,創(chuàng)建一個合約對象,然后進(jìn)行發(fā)布,等待著異步執(zhí)行的方法輸出合約地址contractAddress,這樣就完成了部署。不過這種方式有一個問題,就是在發(fā)布合約時,你的私鑰處于聯(lián)網(wǎng)狀態(tài),
處于安全策略,我們需要盡量避免私鑰在聯(lián)網(wǎng)狀態(tài)。
以太坊上部署合約是向空地址發(fā)送一個附有字節(jié)碼的簽名交易,其中發(fā)送者就是這個合約的擁有者。因此我們只需要將合約構(gòu)建成一筆交易,我們在無網(wǎng)狀態(tài)下對這筆交易進(jìn)行簽名,然后將簽名發(fā)送到以太坊網(wǎng)絡(luò)中。這樣能夠降低我們私鑰被泄漏的風(fēng)險。
對合約的簽名方法如下:
var Tx = require('ethereumjs-tx')
const rawTx = {
nonce: '0x6', //這個是你的地址的交易次數(shù)+1,0開始
gasPrice: '0x12a05f200',
gasLimit: '0x493e0',
data: bytecode,
from: address,
to: ""
};
const tx = new Tx(rawTx);
tx.sign(privateKey);
const serializedTx = tx.serialize();
console.log(serializedTx.toString('hex'))
以上對一個合約簽名,這里需要注意的問題是,to的地址需要是,空地址。
完成簽名之后,我們把這筆交易發(fā)送出去就好,最簡單的方法就是使用etherscan的發(fā)送Tx的方式,一旦發(fā)送完成,部署完成,就可以看到合約地址。