使用nodejs部署智能合約
實(shí)現(xiàn)智能合約的方式很多種,可以用truffle框架來實(shí)現(xiàn)祥楣,編譯,部署汉柒。
這里介紹一種簡單的使用nodejs來實(shí)現(xiàn)误褪,編譯,部署的方法碾褂。
創(chuàng)建一個(gè)nodejs項(xiàng)目兽间,實(shí)現(xiàn)一個(gè)簡單的智能合約。
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);
}
}
這個(gè)合約實(shí)現(xiàn)了一個(gè)造幣和轉(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
,對(duì)BaseToken進(jìn)行編譯帜羊,生成字節(jié)碼。web3中提供了一個(gè)部署合約的接口鸠天,使用如下讼育,
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)建一個(gè)合約對(duì)象稠集,然后進(jìn)行發(fā)布奶段,等待著異步執(zhí)行的方法輸出合約地址contractAddress
,這樣就完成了部署剥纷。不過這種方式有一個(gè)問題痹籍,就是在發(fā)布合約時(shí),你的私鑰處于聯(lián)網(wǎng)狀態(tài)晦鞋,
處于安全策略词裤,我們需要盡量避免私鑰在聯(lián)網(wǎng)狀態(tài)刺洒。
以太坊上部署合約是向空地址發(fā)送一個(gè)附有字節(jié)碼的簽名交易,其中發(fā)送者就是這個(gè)合約的擁有者吼砂。因此我們只需要將合約構(gòu)建成一筆交易逆航,我們在無網(wǎng)狀態(tài)下對(duì)這筆交易進(jìn)行簽名,然后將簽名發(fā)送到以太坊網(wǎng)絡(luò)中渔肩。這樣能夠降低我們私鑰被泄漏的風(fēng)險(xiǎn)因俐。
對(duì)合約的簽名方法如下:
var Tx = require('ethereumjs-tx')
const rawTx = {
nonce: '0x6', //這個(gè)是你的地址的交易次數(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'))
以上對(duì)一個(gè)合約簽名周偎,這里需要注意的問題是抹剩,to的地址需要是,空地址蓉坎。
完成簽名之后澳眷,我們把這筆交易發(fā)送出去就好,最簡單的方法就是使用etherscan的發(fā)送Tx的方式蛉艾,一旦發(fā)送完成钳踊,部署完成,就可以看到合約地址勿侯。