首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

以太坊构建DApps系列教程(二):创建部署TNS代币

在本系列关于使用以太坊构建DApps的文章第1部分中,我们引导大家做了两个版本的本地区块链进行开发:一个Ganache版本和一个完整的私有PoA版本。

在这一部分中,我们将深入研究并构建和部署我们的TNS代币:用户将使用代币对Story DAO中的提案进行投票。

先决条件

按照上一部分,启动并运行Ganache版本。或者,如果你没有从第一部分开始跟踪,则可以运行任何本地版本的区块链,但请确保你可以使用我们需要的工具连接到它。

我们假设你有一个有效的私有区块链,能够通过终端应用程序在其控制台和操作系统终端中输入命令,或者在Windows上,通过Git Bash,Console,CMD Prompt,Powershell等应用程序输入命令。

基本依赖

为了开发我们的应用程序,我们可以使用几种框架和入门开发包中的一种:Dapp,eth-utils,Populus,Embark…等等。但我们会选择现在的生态系统之王Truffle。

使用以下命令安装它:

这将使命令无处不在。现在我们可以用启动项目。

构建代币

让我们直接进入它并构建我们的代币。它将是一个有点标准的千篇一律的ERC20代币。(你会看到这篇文章中那个更标准的。)首先,我们将引入一些依赖关系。OpenZeppelin库是经过实战考验的高质量的合约,可用于扩展和构建合约。

接下来,让我们创建一个新的代币文件:

在这里生成的默认模板有点过时了,所以让我们更新它:

到目前为止,代币合约的构造函数应该与合约本身一样被调用,但为了清楚起见,它被更改为。它也应该总是有一个修饰符告诉编译器谁被允许部署和与此合约交互(public意味着每个人)。

SafeMath

我们将在这种情况下使用的唯一Zeppelin合约是他们的SafeMath合约。在Solidity中,我们使用import关键字导入合约,而编译器通常不需要完整路径,只需要相对的路径,如下所示:

那么,什么是?很久以前,由于代码中的数学问题,出现了1840亿比特币的问题。为了防止类似于这些问题(并非特别只在以太坊中可能存在这一问题),SafeMath库仍然存在。当两个数字具有大小(即操作系统中的最大可能数量)时,将它们相加会使值重新归零,就像汽车的里程表在达到999999公里后重置为0。所以SafeMath库具有以下功能:

此函数可以防止此问题:它检查两个数字的总和是否仍然大于两个操作数中的每一个。

虽然在撰写Solidity合约时犯下如此愚蠢的错误并不容易,但保持安全比抱歉更好。

通过,我们用这些“安全”版本替换Solidity(256bit unsigned - aka positive-only - whole numbers)中的标准数字。而不是像这样求和数:,我们将这样求和:,从而在我们的计算中是安全的。

来自Scratch的ERC20

我们的数学计算安全了,我们可以创建我们的代币。

ERC20是一个定义明确的标准,所以作为参考,我们将它添加到合约中。在这里阅读代币标准 。

所以ERC20代币应该具有的功能是:

这可能看起来很复杂,但实际上非常简单。这是我们代币需要具有的函数的“目录”,我们将逐个构建它们,解释每个函数的含义。考虑上面的代币接口。在创建Story DAO应用程序时,我们将看到它如何以及为何有用。

基本余额

开始吧。代币实际上只是以太坊区块链中的“电子表格”,如下所示:

所以让我们创建一个,它基本上就像合约中的电子表格:

根据上面的接口,这需要伴随一个函数,它可以读取此表:

函数balanceOf接受一个参数:是(可以被任何人使用),是一个函数(意思是它可以自由使用——不需要交易),并返回一个编码,地址所有者的余额放在里面。每个人的代币余额都是公开可读的。

总供应量

知道代币的总供应量对于其用户和代币跟踪应用程序非常重要,所以让我们定义一个合约属性(变量)来跟踪这个和另一个自由函数来读取它:

发送代币

接下来,让我们确保一些代币的所有者可以将它们发送给其他人。我们还想知道发送何时发生,因此我们也将定义发送事件。事件允许我们通过JavaScript监听区块链中的传输,以便我们的应用程序可以知道何时发出这些事件,而不是不断地手动检查传输是否发生。事件与合约中的变量一起声明,并使用关键字发出。我们现在将以下内容添加到合约中:

此函数接受两个参数:,它是将接收代币的目标地址,以及,即代币的数量。重要的是要记住,是代币的最小单位数,而不是整个单位。因此,如果一个代币被声明具有10位小数的话,那么为了发送一个代币,你将发送10000000000。这种粒度级别允许我们处理极小数量。

该函数是公共的,这意味着任何人都可以使用它,包括其他合约和用户,并且如果操作成功则返回。

然后该功能进行一些健全性检查。首先,它检查目标地址是否为空地址。换句话说,不得将代币必须正常发送。接下来,它通过比较它们的余额()和传入的发送值来检查发件人是否甚至被允许发送这么多代币。如果这些检查中的任何一个失败,该函数将拒绝该交易并失败。它将退还所发送的任何代币,但是在此之前用于执行该功能的gas将被花费。

接下来的两行从发件人的余额中减去代币数量,并将该金额添加到目的地余额中。然后使用事件,并传入一些值:发件人,收件人和金额。现在,任何订阅了此合约上的发送事件的客户都将收到此事件的通知。

好的,现在我们的代币持有者可以发送代币。信不信由你,这就是基本代币所需要的一切。但我们已经要超越了这一点,并增加了一些功能。

津贴

有时可能会允许第三方退出其他帐户的余额。这对于可能促进游戏内购买,去中心化交易等的游戏应用非常有用。我们通过构建一个名为的多维实现这一点,该存储了所有这些权限。我们添加以下内容:

这个事件就在那里,以便应用程序可以知道有人预先批准了其他人的余额支出,一个有用的功能,以及标准的一部分。

映射将地址与另一个映射相结合,该映射将地址与数字组合在一起,它基本上形成了一个像这样的电子表格:

所以Bob的余额可能由Mary支付,最多可达1000个代币,Billy最多可达50个代币。Bob可以将Mary的余额花费750代币。Billy的余额最多可以由Mary花费300个,而Joe花费1500。

鉴于此映射是映射,它只能由此合约中的函数和使用此合约作为基础的合约使用。

要批准其他人从你的帐户中扣款,你可以使用允许使用代币的人的地址,允许他们支付的金额以及你发出事件的功能来调用功能:

我们还需要一种方法来读取用户可以从其他用户的帐户中花费多少:

所以它是另一个函数(),这意味着它可以自由执行。它只是读取剩余的可提取余额。

那么如何为别人发送?使用新的功能:

和以前一样,有健全性检查:目标地址不能是空地址,因此不要将代币发送到不存在的地方。发送的值还需要不仅小于或等于发送值当前帐户的余额,而且还需要小于或等于消息发送者(发起此交易的地址)仍然允许为他们花费的余额。

接下来,更新余额并使允许的余额与发出有关发送事件之前的余额同步。

注意:代币持有者可以在不更新映射的情况下代币。如果代币持有者使用手动发送代币,则会发生这种情况。在这种情况下,持有人的代币可能比第三方可以支付的额外费用少。

通过批准和许可,我们还可以创建让代币持有者增加或减少某人津贴的功能,而不是完全覆盖该值。尝试将此作为练习,然后参考下面的源代码以获得解决方案。

构造函数

到目前为止,我们只是建立了一个代币“合约”。但是这个标记是什么?它叫什么?它有多少位小数?我们如何使用它?

在一开始,我们定义了一个函数。现在,让我们完成它的主体并添加属性,和:

这样做可以让我们稍后重复使用同一类型的其他代币。但是,当我们确切知道我们正在构建的内容时,让我们对这些值进行硬编码:

显示代币信息时,各种以太坊工具和平台会读取这些详细信息。将合约部署到以太坊网络时会自动调用构造函数,因此这些值将在部署时自动配置。

关于,这句话只是让人们更容易阅读数字的一种方式。由于以太坊中的所有发送都是使用最小的以太单位或代币(包括小数)完成的,因此最小单位是小数点后18位小数。这就是说单个TNS代币为。此外,我们想要1亿,所以或。这使得数字比更易读。

替代开发方案

或者,我们也可以扩展Zeppelin合约,修改一些属性,然后我们就拥有代币了。这就是大多数人所做的,但在处理可能数百万其他人的钱的软件时,我个人倾向于想知道我在代码中的确切内容,因此盲目代码重用在我的个人情况下是要最小化的。

在这种情况下,我们使用is符号来声明我们的代币是。这使得我们的代币扩展了合约,后者又扩展了,等等…

无论哪种方式,我们的代币现在已准备就绪。但谁得到了多少代币以及如何开始?

初始余额

让我们给合约的制造者所有的代币。否则,代币将不会发送给任何人。通过在其末尾添加以下行来更新:

代币锁定

看到我们打算使用代币作为投票权(即你在投票期间锁定了多少代币代表你的投票有多强大),我们需要一种方法来防止用户在投票后发送它们,否则我们的DAO将容易受到Sybil攻击的影响——拥有一百万个代币的个人可以注册100个地址,并通过将它们发送到不同的地址并使用新地址重新投票来获得1亿个代币的投票权。因此,我们将阻止发送与一个人投票额完全一样多的代币,对每个提案的每次投票都是累积的。这是我们在本文开头提到的扭曲。让我们在合约中添加以下事件:

然后让我们添加锁定方法:

每种方法都确保不会锁定或解锁非法金额,然后在更改给定地址的锁定金额后发出事件。每个函数还返回现在为此用户锁定的新金额。但这仍然不能阻止发送。让我们修改和:

最后,我们需要知道为用户锁定或解锁了多少代币:

就是这样:我们的代币现在可以从外部锁定,但只能由代币合约的所有者锁定(这将是我们将在即将到来的教程中构建的Story DAO)。让我们将代币合约设为,即允许它拥有一个所有者。使用导入;然后更改此行:

…是这样的:

完整代码

此时带有自定义函数注释的代币的完整代码见文末所示。

结论

这部分帮助我们构建了一个基本代币,我们将在中将其用作参与/共享代币。虽然代币具有效用,但它的定义是作为一种资产来控制更大的体量的安全代币。注意区别。

在本系列的下一部分中,我们将学习如何编译,部署和测试此代币。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181222G0Q9M300?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券