抖音技术能力大揭密!钜惠大礼、深度体验,尽在火山引擎增长沙龙,就等你来! 立即报名>> 了解详情
写点什么

以太坊 Dapp 入门实战之代币功能

2018 年 11 月 24 日

以太坊Dapp入门实战之代币功能

在本教程的第一篇文章中,我们介绍了如何搭建简单的投票 dapp,并将其部署在本地机器的测试环境中。在第二篇文章中,我们将这个 dapp 迁移到 truffle 框架上,并将其部署到公开测试网络 Ropsten 上,然后分别通过 truffle 控制台和网页与其交互。接下来我们要再添加一些新功能,以便学习几个新概念。下面是本文要介绍的内容:


  • 学习如何用新的数据类型,比如struct,在区块链上组织和存储数据。

  • 学习代币(token)的概念及其用法。

  • 学习如何使用以太币,即以太坊区块链平台上的货币,进行支付。


本文所涉及的代码全部放在代码库 https://github.com/maheshmurthy/ethereum_voting_dapp 的 chapter3 目录下。


通常在选举时,每位选民可以投一票给自己喜欢的候选人。然而在选举公司的董事会主席时,是根据股东所持有的股份来计算票数的。也就是说股东持有的股数越多,可以投的票数也越多。


接下来我们要让这个投票 dapp 支持这种选举。因此要添加购买公司股份的功能,然后根据自己所持有的股数投票给候选人。另外还要添加一个功能,查看投票者的信息。在以太坊区块链上,这些股份一般被称作代币,因此后面我们也用代币这种叫法。


如果你想直接去看看合约文件,可以访问:https://github.com/maheshmurthy/ethereum_voting_dapp/blob/master/chapter3/contracts/Voting.sol


第一步是声明变量,我们要用这些变量存放所有我们感兴趣的信息。下面就是合约中的变量及其含义。


// 我们用struct存放投票者的信息  struct voter {    address voterAddress; // 投票者的地址    uint tokensBought;    // 投票者持有的代币总数    uint[] tokensUsedPerCandidate; // 这个数组中存放给每个候选人的代币数    /* 下面有个名为candidateList的数组。投票者每次用代币    给候选人投票,对应位置的值就会增加。比如说,如果    candidateList数组声明为["Rama", "Nick", "Jose"],并且这位    投票者给Nick投了10代币,则    tokensUsedPerCandidate[1] 的值会加10。     */  }/* 映射表就相当于关联数组或哈希表。 映射表的键是候选人的名称,用bytes32类型记录;值是无符号整型,用来存放票数。 */mapping (bytes32 => uint) public votesReceived;mapping (address => voter) public voterInfo;/* Solidity中还不能直接返回字符串数组。所以我们会用一个bytes32数组存放候选人。 */bytes32[] public candidateList;uint public totalTokens; // 这次选举可用的代币总数。uint public balanceTokens; // 还可以购买的代币总数uint public tokenPrice; // 代币的价格
复制代码


在前两篇文章中,我们在构造器中初始化了一个包含候选人的列表。可构造器只有在合约部署到区块链上时才会运行一次。我们在这里也要初始化可销售的代币总数和每个代币的价值。所以构造器需要调整一下:


/* 在合约部署到区块链上时初始化可销售的代币总数和每个代币的价值,以及所有的候选人。 */  function Voting(uint tokens, uint pricePerToken, bytes32[] candidateNames) public {    candidateList = candidateNames;    totalTokens = tokens;    balanceTokens = tokens;    tokenPrice = pricePerToken;  }
复制代码


在 truffle 中,是用迁移将代码将合约部署到区块链上。你可以看一下这里的迁移文件。truffle 迁移文件中的部署代码看起来是这样的:


deployer.deploy(Voting, 1000, web3.toWei('0.1', 'ether'), ['Rama', 'Nick', 'Jose']);// 1000是可销售的代币总数,每个代币的价格是0.1以太币// 稍后我们还会看到这段代码。
复制代码


在初始化好代币及其价格之后,我们来看看如何用以太币购买这些代币。下面这个是购买代币的函数。


/* 这是购买代币的函数,注意下面的关键字'payable'。只要在函数声明中加入这个关键字,合约就可以接受调用该函数者提供的以太币。收钱不可能比这更容易了。 */function buy() payable public returns (uint) {    uint tokensToBuy = msg.value / tokenPrice;    if (tokensToBuy > balanceTokens) throw;    voterInfo[msg.sender].voterAddress = msg.sender;    voterInfo[msg.sender].tokensBought += tokensToBuy;    balanceTokens -= tokensToBuy;    return tokensToBuy;}
复制代码


调用这个购买函数的示例如下所示:


truffle(development)> Voting.deployed().then(function(contract) {contract.buy({value: web3.toWei('1', 'ether'), from: web3.eth.accounts[1]})})
复制代码


在函数buy() 中,可以用msg.value访问参数 value: web3.toWei(‘1’, ‘ether’),而msg.sender会给我们web3.eth.accounts[1]的账号地址。也就是说按照上面的代码,假如每个代币的价格是 0.1 以太币,则web3.eth.accounts[1]将会收到 1 /0.1 = 10 个代币。


我们先把代码放一放,看一下这幅图,看看账户(投票者)和合约之间是如何交互的。



正如github上的合约文件所示,其他新方法大多是取值方法,应该很容易看懂。


index.html文件也有些更新:


  1. 要投票给候选人,必须设定投票用的代币数。

  2. 还多了一个购买代币的区域。

  3. 现在你可以查看投票者的信息,他们持有多少代币以及用多少代币给每个候选人投票。

  4. 候选人不再是硬编码在文件中的了,而是从区块链中读取出来的。


app.js文件中也有变化,以实现 UI 中的新增功能。


更新部署文件 2_deploy_contracts.js,传入代币总数,代币价格以及候选人的名字。


var Voting = artifacts.require("./Voting.sol");module.exports = function(deployer) {  deployer.deploy(Voting, 1000, web3.toWei('0.1', 'ether'), ['Rama', 'Nick', 'Jose']);};
复制代码


所以这里总共更新了四个文件,分别是 Voting.sol、index.html、app.js 和 2_deploy_contracts.js。 所以只要你更新了这四个文件,就可以将合约部署到区块链上了。部署过程跟我们之前介绍的一样。


只需要用 truffle 命令就可以完成编译和迁移。


maheshmurthy|~/dev/ethereum_voting_dapp/chapter3$ truffle migrate

Using network ‘development’.

Compiling Migrations.sol…

Compiling Voting.sol…

Writing artifacts to ./build/contracts

Running migration: 1_initial_migration.js

Deploying Migrations…

Migrations: 0xc9249947010675b8a3b1defb12334148f7f59010

Saving successful migration to network…

Saving artifacts…

Running migration: 2_deploy_contracts.js

Deploying Voting…

Voting: 0x795d6d1f7cf467f27e48181da5f1ebd5bbd0a8df

Saving successful migration to network…

Saving artifacts…


在合约部署成功后,启动 web 服务器,你就能看到如下所示的页面:



正如你在上面的界面中看到的那样,你可以购买代币,用代币投票给候选人,通过地址查看投票者的信息。如果这些功能都没问题,恭喜你!


我希望你能通过这个教程认识到什么是以太坊,它能做什么,以及如何搭建去中心化应用。


2018 年 11 月 24 日 09:00775

评论 1 条评论

发布
暂无评论
发现更多内容

Elasticsearch document 的 _source 元数据

escray

elastic 七日更 28天写作 死磕Elasticsearch 60天通过Elastic认证考试

Nine Ring九环智能合约软件开发|Nine Ring九环智能合约APP系统开发

开發I852946OIIO

系统开发

点位盘,点位盘开发,点位盘合约交易。

v16629866266

2021面试脚本!夜读互联网Java开发27大专题,终入P7

比伯

Java 程序员 面试 计算机 技术宅

AWS CDK | IaC 何必只用 Yaml

郭旭东

AWS 基础设施即代码 IaC

Linux:为什么性能工具需要 BPF 技术

博文视点Broadview

2020年终总结:回顾、反思、期待

书旅

年终总结

Spring Boot 中集成ActiveMQ

武哥聊编程

Java springboot SpringBoot 2 28天写作 Activemq

MDF智能合约APP开发|MDF智能合约软件系统开发

开發I852946OIIO

系统开发

数据库运维家中常备:上限约400MB/s,比COPY等工具还好用的数据利器

华为云开发者社区

数据 GaussDB 数据迁移 gds FDW

悟透前端 | ECMAScript 6的Map映射

devpoint

json 前端 map ES6

刷屏的微信8.0(文末附安卓下载链接) | 视频号 28 天 (15)

赵新龙

28天写作

软件测试--cookie学习

测试人生路

软件测试

美团图数据库平台建设及业务实践

Nebula Graph

图数据库

如何成为一名优秀的技术Leader?

架构精进之路

成长笔记 七日更 28天写作

数据结构与算法 - 哈夫曼树

ios 数据结构与算法

腾讯T3大佬亲自教你!一起刷完了这份1307页的安卓面试宝典吧,吐血整理

欢喜学安卓

android 程序员 面试 移动开发

深度解读设备的“万能语言”鸿蒙系统的分布式软总线能力

华为云开发者社区

鸿蒙 操作系统 智能设备 HarmonyOS 分布式软总线

HPC on Volcano:容器在气象行业HPC高性能计算场景的应用

华为云原生团队

大数据 容器 云原生 k8s 分布式计算

图说丨京东《技术重构社会供应链——未来科技趋势白皮书》

京东科技开发者

京东 智能供应链

基于机器学习的逻辑回归模型

无誉

数字货币呼之欲出,但这些套路须警惕!

CECBC区块链专委会

数字货币

联动链金-魔方支付体系整理

第一周

Richard

全网最详细的负载均衡原理图解

程序员小毕

Java 负载均衡 性能优化 运维 服务器

如何理解新技术带来的新资产类别?

CECBC区块链专委会

区块链

基于用户画像/AB测试的产品定价

无誉

程序员的简历,要注意以下几点

田维常

简历

一文带你搞懂从动态代理实现到Spring AOP

华为云开发者社区

spring jdk 容器 aop 动态代理

2021年数字货币时代加速到来

CECBC区块链专委会

数字人民币

首发!腾讯开源“百万级”Netty进阶指南(2021最新)

程序员小毕

Java Netty 网络 框架 异步编程

Study Go: From Zero to Hero

Study Go: From Zero to Hero

以太坊Dapp入门实战之代币功能-InfoQ