详细分析DApp质押挖矿分红系统合约开发部署方案

详细分析DApp质押挖矿分红系统合约开发部署方案

DApp是什么

DApp( Decentralized Application )即分布式应用或去中心化应用。DApp就是智能合约+App。

一个真正的DApp应用,需要同时满足以下几个条件:

应用必须完全开源、自治,且没有一个实体控制该应用超过51%的- Token。该应用必须能够根据用户的反馈及技术要求进行升级,且应用升级必须由大部分用户达成共识之后方可进行;

应用的数据必须加密后存储在公开的区块链上;

应用必须拥有Token机制,矿工或应用维护节点需得到代币奖励;

应用代币的产生必须依据标准的加密算法,有价值的节点可以根据该算法获取应用的代币奖励。

DApp原理

一个DApp被调用之前需要先部署到以太坊上,不管是私链,公链还是联盟链。故本章节分为两部分,DApp部署原理和调用原理。

部署

一个DApp由多个智能合约组成,部署一个DApp也就是同时部署多个智能合约,这里讲述一下部署一个智能合约的流程。

以太坊Web3.js提供调用合约的方法一共有四种:

call: 这是最简单的调用方式,适用于调用只读的方法,也就是调用过程不会修改区块链上的数据,因为它只读取本地数据即可,因此不会消耗gas,而且可以立刻获得返回值,适用于前端调用,具体例子如下。

//合约声明

contract test {

function multiply(uint a) returns(uint d) {

return a * 7;

}

}

//合约调用

var Multiply7 = eth.contract(contract.info.abiDefinition);

var myMultiply7 = Multiply7.at(address);

myMultiply7.multiply.call(3)

sendTransaction: 可调用读或写方法,调用过程会创建一个交易,调用之后会返回一个交易hash值,它会广播到网络,等待矿工打包, 它会消耗gas,而且该调用不能立刻获得返回值,只能从event log中获取,也是适用于前端调用,代码如下。

wheelOfFortune.makeBet.sendTransaction(num – 1, betCount, tips, { from: web3.eth.accounts[0], value: betUnit \* betCount + tips }).then(function (result) {

if (result.logs.length > 0) {

var eventobj = result.logs[0].args;

$.ajax({

url: /Wheel/makeBet/ + eventobj.pieceIdx + / + betCount + / + tips + / + web3.eth.accounts[0],

success: function (data) {

var nextRound = JSON.parse(data);

$(“#currentTotal”).text(nextRound.betPool.toLocaleString());

playersNumberOfPiece = nextRound.playersNumberOfPiece;

alert(成功);

}

});

}

});

直接调用: 这是一种特殊调用,可以说是前两种调用的结合,因为当合约方法有constant修饰时,直接调用会等同于call,否则等同于sendTransaction。

var winIdx = (Math.random() \* wheel.config.pieceCount) >> 0;

// 后台调用infura部署的合约必须用sendRawTransaction

var coder = require(web3/lib/solidity/coder);

var CryptoJS = require(crypto-js);

var Tx = require(ethereumjs-tx);

var privateKey = new Buffer(“71112e795325d5cbf14d665091ce4626f26c8342b8038f1adcdfff26be04a220”, hex);

var functionName = finishRound;

var types = [uint];

var args = [winIdx];

var fullName = functionName + ( + types.join() + );

var signature = CryptoJS.SHA3(fullName, { outputLength: 256 }).toString(CryptoJS.enc.Hex).slice(0, 8);

var dataHex = signature + coder.encodeParams(types, args);

var data = 0x + dataHex;

var account = “0x4BEB9EA54fc912B619D5C682BA1cB3524bc80955”;

var nonce = web3.toHex(web3.eth.getTransactionCount(account));

var gasPrice = web3.toHex(web3.eth.gasPrice);

var gasLimitHex = web3.toHex(3000000);

var rawTx = { nonce: nonce, gasPrice: gasPrice, gasLimit: gasLimitHex, from: account, to: contractAddress, data: data }

var tx = new Tx(rawTx)

tx.sign(privateKey)

var serializedTx = 0x + tx.serialize().toString(hex)

web3.eth.sendRawTransaction(serializedTx, function (err, txHash) {

if (!err) {

console.log(JSON.stringify({ “transactionHash”: txHash }));

} else {

console.log(“finish round error ” + err);

}

});

sendRawTransaction: 前两种方法都不需要调用者提供交易发起者的私钥进行方法签名,因为MetaMask或本地以太坊节点提供了,但是当我们没有MetaMask时调用公链合约,我们只能调用sendRawTransaction使用指定账户的私钥签名方法后才能调用合约,值得注意的是,该方法我们无法获得返回值,即使在event log中也拿不到,只能在得到transaction的hash后再读取区块链信息才可以,一般在后台调用方法时用到。

调用时需要注意的几点:

当调用者给予Gas不足时,EVM会报出out of gas的错误,这时候会回滚本地交易所做过的所有修改,好在以太坊还提供了estimategas方法,可以让我们在调用之前预估交易所需的Gas,因为Solc编译器会算出每一句代码的价格,不过有时会不准确,特别是出现死循环或者违反了修饰方法的限制条件时。

调用频率不能过快,一方面所有调用方法都是异步的,返回时间可能会较长,另一方面有可能第一次调用的transaction还没被挖到区块中,下一次调用就来了,而且两次调用的hash可能是一样的,所以就会报replacement transaction underpriced错误。

当我们调用了不存在的方法时,EVM会自动调用合约中的Fallback方法作为兜底,而且会将Gas全耗完,如果没有定义Fallback方法,才会报错回滚。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Proudly powered by WordPress | Theme: HoneyWaves by SpiceThemes