以太坊 智能合约
面对现实吧。 对于智能合约,实现两个整数的加法不是很“智能”。 在本文中,我将尝试超越以前的琐碎示例,并提出一个简单但真实的用例。
这是4在开始复仇重点series.Other帖子后第包括:
- 从以太坊开始-设置
- 以太坊开始-撰写合约
- 从以太坊开始-部署和运行合同
- 从以太坊开始-智能合约 (本文)
- 从以太坊开始-工业化
例如,让我们考虑公投的商业领域。
全民投票用例
全民投票是直接投票,邀请整个选民就特定提案进行投票。
https://zh.wikipedia.org/wiki/公民投票
为了使博客文章变得简单,应该没有太多要求。 这是一些非常简单的方法:
- 每个公投有x票。 让我们将这样的投票命名为“投票令牌”。
- 一个帐户可以提交多个投票令牌。 换句话说,无需检查帐户是否提交了一个或多个令牌。
- 投票是公开的。 第三方可以检查哪个帐户提交了哪些令牌。 换句话说,任何人都可以检查交易和创建交易的人-这是区块链的好处。
但是,将帐户绑定到特定身份并非易事。
- 答案可以是“是”,“否”或“空白”。
- 创建公投的帐户也会获得所有初始投票令牌的贷记。 由创建帐户将令牌分配给其他帐户,以便他们可以提交它们。
- 在任何时候,都可以查询提交的投票令牌的状态。
- 当所有投票令牌都已投出时,应计算结果。
- 任何帐户都可以订阅最终结果。
该模型
这是概念模型的建议:
- 与公民投票相关的可用投票令牌数量有限。
- 投票有一个特定的答案。
和序列图:
特征,概念模型和序列如何转换为Solidity实现模型?
第一步是设计投票令牌对象本身。 需要一个注册表,该注册表引用哪个帐户拥有哪个金额。 以太坊是通过设计来创建自定义加密货币的。 他们为此提供了可靠的文档和一些代码模板。 这很好地转换为投票令牌。 我刚刚对代码进行了一些更新,以更好地满足要求:
- 删除名称,一个符号绰绰有余
- 转移投票令牌只能来自令牌所有者-函数调用者。 在创建合同后将使用此选项,以将其分配给选民帐户。 之后也可以使用它,将投票令牌传递给另一个帐户。
- 另一方面,从公投合同中将调用燃烧令牌即使用令牌,并且需要引用原始调用者(请参见下文)。
代码
完整的源代码在这里 。
让我们重点介绍一些有趣的功能。 听到此事的是castVotes()
函数。
function castVotes(Answer _answer, uint256 _count) public {
require(referendum.open); (1)
VotingToken tokenContract = VotingToken(tokenAddress); (2)
tokenContract.burn(msg.sender, _count); (3)
handleVotes(_answer, _count); (4)
Vote(msg.sender, _answer, _count); (5)
if (hasAllVotes()) {
close();
}
}
-
require
是Solidity 关键字,用于管理“ 合同编程设计”中的前提条件。 失败的require
将回滚当前调用期间传递的任何状态。 在这里,我们不允许对封闭合同实例进行投票。 - 创建对现有合同的引用! 这是以太坊最重要的功能之一:一个合约实例可以调用另一个合约实例的方法,因此跨合约链接方法调用。
- 有效地调用合同实例的
burn()
方法。 请注意,呼叫者帐户作为参数传递-为了从帐户中删除投票代币。 - 增加投票数。
- 发送事件。 事件本质上是区块链日志,但它们也允许从JavaScript客户端进行订阅。
另一个有趣的地方是以下功能:
function getResults() public view returns (uint256 yesCount, uint256 noCount, uint256 blankCount) {
return (referendum.votes.yesCount, referendum.votes.noCount, referendum.votes.blankCount);
}
对于Java开发人员来说,这可能令人惊讶,但是Solidity不仅可以返回多个值,而且可以命名它们以提高可维护性。
另外,请注意view
修饰符。 在编写第一个合同时 ,我们使用了pure
修饰符。 pure
表示返回值仅取决于输入参数-因此,不会写入或读取区块链。 view
修饰符表示没有写入,但可能有读取。
如果没有阅读,则修饰符不应是视图,而应是纯净的
用法
让我们在Remix网络上部署两个合同:
然后开始与已部署的合同进行交互:
varreferendumContract=web3.eth.contract(<content/of/ABI>);
varreferendumContractInstance=referendumContract.at('0x48dbcdd695fb6a7728dc656abd8baa460d7ff081');
referendumContractInstance.getQuestion();
这产生了我初始化投票的问题-检查是否需要。
此时,应该将投票令牌分配给其他帐户。 但是,直接从主帐户进行投票比较容易。
referendumContractInstance.castVote(0);
referendumContractInstance.getResults();
有趣的是,当从控制台调用castVote()时,我得到了一个异常,但它在电子钱包中有效。 可能是因为我没有登录控制台。
如上所述,Solidity事件会写入区块链。 但是,也可以通过事件从web3.js收听它们。 每当将Finish
事件写入到区块链时,以下代码就会触发(通过close()
方法)。
varfinishEvent=referendumContractInstance.Finish();
varconsoleLog=function(error,result){
if(error){
console.log(error);
} else{
console.log("Referendum "+result.args._referendum+" finished");
}
}
finishEvent.watch(consoleLog);
结论
至此,我们真正进入了智能合约。 设计的合同具有一定程度的业务逻辑。 我们看到了一些Solidity功能:事件, require
, view
以及如何从另一个调用合同。
在您方面,您可以重复使用Solidity源 ,在此基础上构建,然后将自己的公投部署到区块链。
以太坊 智能合约