如何:在PIRL网络上创建令牌

分享这个帖子

分享到!trpst#/trp-gettext>
分享到!trpst#/trp-gettext>
分享到!trpst#/trp-gettext>
分享到!trpst#/trp-gettext>

硬币

我们将创建一个数字令牌。 Pirl生态系统中的令牌可以代表任何可替代的可交易商品:硬币,积分,金券,借据,游戏中的物品等。由于所有令牌都以标准方式实现一些基本功能,因此这也意味着您的令牌将立即可用与Pirl钱包以及使用相同标准的任何其他客户或合同兼容。

最低可行令牌

标准令牌合约可能非常复杂。但实际上,一个非常基本的令牌可以归结为:

contract MyToken {/ *这将创建一个具有所有余额的数组* /映射(地址=> uint256)public balanceOf; / *使用向合同创建者提供的初始供应令牌初始化合同* /函数MyToken(uint256 initialSupply){balanceOf [msg.sender] = initialSupply; //给创建者所有初始令牌} / *发送硬币* /函数传递(地址_to,uint256 _value){require(balanceOf [msg.sender]> = _value); //检查发件人是否有足够的require(balanceOf [_to] + _value> = balanceOf [_to]); //检查是否有溢出balanceOf [msg.sender]-= _value; //减去发件人balanceOf [_to] + = _value; //将其添加到收件人}}

代码

但是,如果您只想复制粘贴更完整的代码,请使用以下代码:

语用强度^ 0.4.16;

interface tokenRecipient {function receiveApproval(address _from,uint256 _value,address _token,字节_extraData)public; }

合约TokenERC20 {
   //令牌的公共变量
   字符串公共名称;
   字符串公共符号;
   uint8公共小数= 18;
   //强烈建议使用18位小数,避免更改它
   uint256 public totalSupply;

   //这将创建一个具有所有余额的数组
   映射(address => uint256)public balanceOf;
   映射(地址=>映射(地址=> uint256))公共津贴;

   //这会在区块链上生成一个公共事件,该事件将通知客户
   事件传输(地址从索引开始,地址从索引开始,uint256值);

   //这会通知客户有关消耗的金额
   事件刻录(地址从uint256值索引);

   /**
    *构造函数
    *
    *使用初始供应令牌向合同创建者初始化合同
    */
   函数TokenERC20(
       uint256 initialSupply,
       字符串tokenName,
       字符串令牌
   ) 上市 {
       totalSupply = initialSupply * 10 ** uint256(十进制); //用小数位数更新总供给
       balanceOf [msg.sender] = totalSupply; //为创建者提供所有初始令牌
       名称= tokenName; //设置显示名称
       符号= tokenSymbol; //设置用于显示目的的符号
   }

   /**
    *内部转帐,只能由本合同调用
    */
   函数_transfer(address _from,address _to,uint _value)内部{
       //防止传送到0x0地址。使用burn()代替
       require(_to!= 0x0);
       //检查发件人是否足够
       require(balanceOf [_from]> = _value);
       //检查溢出
       require(balanceOf [_to] + _value> balanceOf [_to]);
       //将其保存为将来的断言
       uint previousBalances = balanceOf [_from] + balanceOf [_to];
       //从发件人减去
       balanceOf [_from]-= _value;
       //将其添加到收件人
       balanceOf [_to] + = _value;
       转移(_from,_to,_value);
       //断言用于使用静态分析来查找代码中的错误。他们永远不会失败
       assert(balanceOf [_from] + balanceOf [_to] == previousBalances);
   }

   /**
    *转移令牌
    *
    *从您的帐户向`_to`发送`_value`令牌
    *
    * @param _to收件人的地址
    * @param _value发送的金额
    */
   函数传递(地址_to,uint256 _value)public {
       _transfer(msg.sender,_to,_value);
   }

   /**
    *从其他地址转移令牌
    *
    *代表“ _from”将“ _value`令牌发送到“ _to”
    *
    * @param _from发件人的地址
    * @param _to收件人的地址
    * @param _value发送的金额
    */
   函数transferFrom(address _from,address _to,uint256 _value)public return(布尔成功){
       require(_value <= allowance [_from] [msg.sender]); //检查津贴
       allowance [_from] [msg.sender]-= _value;
       _transfer(_from,_to,_value);
       返回true;
   }

   /**
    *设置其他地址的津贴
    *
    *允许_spender代表您花费的代币不超过_value令牌
    *
    * @param _spender授权使用的地址
    * @param _value他们可以花费的最大金额
    */
   函数批准(地址_spender,uint256 _value)公共
       回报(成功成功){
       allowance [msg.sender] [_ spender] = _value;
       返回true;
   }

   /**
    *设置其他地址的限额并通知
    *
    *允许_spender代表您花费的令牌数不超过_value,然后对其执行ping操作
    *
    * @param _spender授权使用的地址
    * @param _value他们可以花费的最大金额
    * @param _extraData一些额外的信息发送到批准的合同
    */
   函数approveAndCall(地址_spender,uint256 _value,字节_extraData)
       上市
       回报(成功成功){
       tokenRecipient支出者= tokenRecipient(_spender);
       如果(批准(_spender,_value)){
           Experer.receiveApproval(msg.sender,_value,this,_extraData);
           返回true;
       }
   }

   /**
    *销毁令牌
    *
    *不可撤销地从系统中删除“ _value”令牌
    *
    * @param _value消耗的金额
    */
   函数burn(uint256 _value)公共返回(布尔成功){
       require(balanceOf [msg.sender]> = _value); //检查发件人是否足够
       balanceOf [msg.sender]-= _value; //从发件人减去
       totalSupply-= _value; //更新totalSupply
       刻录(msg.sender,_value);
       返回true;
   }

   /**
    *从其他帐户销毁令牌
    *
    *代表`_from`不可撤销地从系统中删除`_value`令牌。
    *
    * @param _来自发件人的地址
    * @param _value消耗的金额
    */
   函数burnFrom(地址_from,uint256 _value)公共返回(布尔成功){
       require(balanceOf [_from]> = _value); //检查目标余额是否足够
       require(_value <= allowance [_from] [msg.sender]); //检查津贴
       balanceOf [_from]-= _value; //减去目标余额
       allowance [_from] [msg.sender]-= _value; //减去发件人的津贴
       totalSupply-= _value; //更新totalSupply
       Burn(_from,_value);
       返回true;
   }
}

了解代码

因此,让我们从基础开始。打开电子钱包应用,转到合同标签,然后部署新合同。在“ Solidity Contract源代码”文本字段上,输入以下代码:

合同MyToken {
       / *这将创建一个带有所有余额的数组* /
       映射(address => uint256)public balanceOf;
   }

映射表示关联数组,您可以在其中将地址与余额相关联。地址采用基本十六进制Pirl格式,而余额为整数,范围从0到115 quattuorvigintillion。如果您不知道quattuorvigintillion是多少,那么比您计划将其令牌使用的数量多得多。 public关键字,意味着该变量将可由区块链上的任何人访问,这意味着所有余额都是公开的(根据需要,以便客户显示它们)。

如果您立即发布合同,那么它会起作用,但不是很有用:它将是一个可以查询硬币余额的地址的合同,但是由于您从未创建过一个硬币,因此每个硬币都会返回0。因此,我们将在启动时创建一些令牌。将此代码添加到最后一个右括号之前,即映射行下方。

函数MyToken(){
       balanceOf [msg.sender] = 21000000;
   }

请注意,函数MyToken与合同MyToken具有相同的名称。这非常重要,如果您重命名一个,则也必须重命名另一个:这是一个特殊的启动功能,仅在合同首次上载到网络时才运行一次。此功能将为部署合同的用户msg.sender设置余额,余额为2100万。

选择2100万是相当随意的,您可以将其更改为代码中所需的任何内容,但是有一种更好的方法:相反,将其作为函数的参数提供,如下所示:

函数MyToken(uint256 initialSupply)public {
       balanceOf [msg.sender] = initialSupply;
   }

看一下合同旁边的右列,您会看到一个下拉列表,写着选择合同。选择“ MyToken”合约,您将看到它现在显示一个名为“ Constructor parameters”的部分。这些是令牌的可变参数,因此您可以重复使用相同的代码,并且以后仅更改这些变量。

现在,您拥有一个可以创建代币余额的功能合同,但是由于没有任何移动它的功能,因此它所要做的就是保留在同一帐户中。所以我们现在要实现它。在最后一个括号之前编写以下代码。

/ *发送硬币* /
   函数传递(地址_to,uint256 _value){
       / *加减新余额* /
       balanceOf [msg.sender]-= _value;
       balanceOf [_to] + = _value;
   }

这是一个非常简单的函数:它有一个接收者和一个值作为参数,每当有人调用它时,它将从他们的余额中减去_value并将其添加到_to余额中。马上就有一个明显的问题:如果该人想要发送的邮件超过自己的所有,会发生什么?由于我们不想处理该特定合同中的债务,因此我们只是要进行快速检查,如果发件人没有足够的资金,则合同执行将停止。它还要检查溢出,以免数字太大而又变成零。

要在执行过程中停止合同执行,您可以返回或抛出合同。前者的耗油量较少,但由于您至今对合同所做的任何更改都将保留,因此头疼可能会更大。另一方面,“投掷”将取消所有合同执行,恢复交易可能进行的任何更改,并且发送方将丢失他发送的所有加油站Pirl。但是由于电子钱包可以检测到合同将要抛出,因此它始终会显示警报,因此根本无法使用任何Pirl。

函数传递(地址_to,uint256 _value){
       / *检查发件人是否余额和是否溢出* /
       require(balanceOf [msg.sender]> = _value && balanceOf [_to] + _value> = balanceOf [_to]);

       / *加减新余额* /
       balanceOf [msg.sender]-= _value;
       balanceOf [_to] + = _value;
   }

 

现在缺少的只是有关合同的一些基本信息。在不久的将来,这可以由令牌注册中心处理,但是现在我们将它们直接添加到合同中:

字符串公共名称;
字符串公共符号;
uint8公共小数;

现在,我们更新构造函数,以允许在开始时设置所有这些变量:

/ *使用初始供应令牌向合同创建者初始化合同* /
   函数MyToken(uint256 initialSupply,字符串tokenName,字符串tokenSymbol,uint8 decimalUnits){
       balanceOf [msg.sender] = initialSupply; //为创建者提供所有初始令牌
       名称= tokenName; //设置显示名称
       符号= tokenSymbol; //设置用于显示目的的符号
       小数位= decimalUnits; //用于显示的小数位数
   }

最后,我们现在需要称为事件的somPirling。这些特殊的空函数可以调用,以帮助诸如Pirl Wallet之类的客户跟踪合同中发生的活动。活动应以大写字母开头。在合同开始处添加以下行以声明事件:

事件传输(地址从索引开始,地址从索引开始,uint256值);
 

然后,您只需要在“转移”函数中添加这两行:

      / *通知任何收听此转移的人* /
       转账(msg.sender,_to,_value);

 

现在,您的令牌已准备就绪!

注意到评论了吗?

您可能会问那些@notice和@param注释是什么?那是 纳特规格 一种自然语言规范的新兴标准,该标准允许钱包向用户显示合同即将执行的自然语言描述。虽然目前还没有很多钱包支持,但是将来会有所改变,因此很高兴做好准备。

如何部署

如果您还没有,请打开Pirl Wallet,转到“合同”标签,然后单击“部署新合同”。

现在从上方获取令牌源,并将其粘贴到“ Solidity source字段”中。如果代码编译没有错误,则应该在右侧看到“选择合同”下拉列表。获取它并选择“ MyToken”合同。在右列,您将看到个性化自己的令牌所需的所有参数。您可以随意调整它们。

滚动到页面末尾,您将看到该合同的计算成本估算,并且可以选择愿意为Pirl支付多少费用。您不花的多余Pirl都将退还给您,因此您可以根据需要保留默认设置。按“部署”,输入您的帐户密码,然后等待几秒钟,以便提取您的交易。

您将被重定向到首页,您可以在其中看到等待确认的交易。单击该帐户,不超过一分钟后,您应该看到您的帐户将显示您刚创建的共享中有100%。要将一些钱发送给几个朋友:选择“发送”,然后选择您要发送的货币(Pirl或新创建的份额),将朋友的地址粘贴到“收件人”字段上,然后按“发送”。

如果您将其发送给朋友,他们的钱包中将看不到任何东西。这是因为钱包仅跟踪其知道的令牌,因此您必须手动添加这些令牌。现在转到“合同”选项卡,您应该会看到指向新创建的合同的链接。单击它转到其页面。由于这是一个非常简单的合同页面,因此这里不需要做很多事情,只需单击“复制地址”并将合同地址粘贴到文本编辑器中,您很快就会需要它。

要添加要观看的令牌,请转到合同页面,然后单击“观看令牌”。将会出现一个弹出窗口,您只需要粘贴合同地址。令牌名称,符号和十进制数字应自动填写,但如果不是,您可以放任何您想要的东西(这只会影响它在钱包中的显示方式)。完成此操作后,系统会自动显示该令牌的余额,并将其发送给其他任何人。

现在您有了自己的加密令牌!令牌本身可以用作本地社区的价值交换,跟踪工作时间或其他忠诚度计划的方式。但是我们可以通过使货币有用来使它具有内在价值吗?

改善您的代币

您无需部署任何代码即可部署整个加密令牌,但是真正的魔力发生在您开始对其进行自定义时。以下各节将为您提供一些建议,这些功能可以添加到令牌中以使其更适合您的需求。

更多基本功能

您会注意到,基本令牌合同中还有其他功能,例如批准,sendFrom和其他功能。这些功能可让您的令牌与其他合同进行交互:例如,如果您想将令牌出售给去中心化交易所,仅将其发送到某个地址是不够的,因为交易所将不会知道新的令牌或谁发送了令牌他们,因为合同不能只订阅事件到函数调用。因此,对于合同,您应该首先批准一定数量的令牌,这些令牌可以从您的帐户中转移出来,然后对它们进行ping操作,以使他们知道自己应该做的事情,或者使用approveAndCall一起执行两个操作。

由于许多这些功能都必须重新实现令牌的传输,因此将它们更改为内部功能是有意义的,该功能只能由合同本身调用:

/ *内部转帐,只能由此合同调用* /
   函数_transfer(address _from,address _to,uint _value)内部{
       要求(_to!= 0x0); //防止传送到0x0地址。使用burn()代替
       要求(balanceOf [_from]> = _value); //检查发件人是否足够
       要求(balanceOf [_to] + _value> balanceOf [_to]); //检查溢出
       require(!frozenAccount [_from]); //检查发件人是否冻结
       require(!frozenAccount [_to]); //检查收件人是否冻结
       balanceOf [_from]-= _value; //从发件人减去
       balanceOf [_to] + = _value; //将其添加到收件人
       转移(_from,_to,_value);
   }

现在,导致硬币转移的所有函数都可以进行自己的检查,然后使用正确的参数调用转移。请注意,此功能会将硬币从任何帐户转移到任何其他帐户,而无需任何人允许:这就是为什么它是内部功能,仅由合同调用的原因:如果添加任何调用它的功能,请确保它正确验证了呼叫者应有权移动这些呼叫者。

集中管理员

默认情况下,所有dapp都是完全去中心化的,但这并不意味着它们就不能拥有某种类型的中央管理器。也许您想要铸造更多硬币的功能,也许您想禁止某些人使用您的货币。您可以添加任何这些功能,但要注意的是您只能在开始时添加它们,因此所有代币持有者在决定拥有一个游戏规则之前,始终会确切地知道游戏规则。

为此,您需要一个货币中央控制器。这可能是一个简单的帐户,但也可能是一个合同,因此,创建更多代币的决定将取决于合同:如果是可以投票的民主组织,或者可能只是限制投票的一种方式。代币拥有者的权力。

为此,我们将学习合同的一个非常有用的属性:继承。继承允许合同获取父合同的属性,而不必重新定义所有属性。这使代码更整洁,更易于重用。在合同MyToken {之前,将此代码添加到代码的第一行。

合同拥有{
       向公共所有者讲话;

       函数owner(){
           所有者= msg.sender;
       }

       仅修饰符所有者{
           require(msg.sender == owner);
           _;
       }

       函数transferOwnership(address newOwner)onlyOwner {
           owner = newOwner;
       }
   }

这创建了一个非常基本的合同,除了定义可以被“拥有”的合同的一些通用功能外,它什么也不做。现在,下一步就是将文本归您所有:

 MyToken拥有的合同{
       / *合同其余部分照常* /

这意味着MyToken中的所有函数现在都可以访问变量owner和修饰符onlyOwner。合同还具有转移所有权的功能。由于在启动时设置合同的所有者可能很有趣,因此也可以将其添加到构造函数中:

函数MyToken(
       uint256 initialSupply,
       字符串tokenName,
       uint8 decimalUnits,
       字符串tokenSymbol,
       地址centralMinter
       ) {
       if(centralMinter!= 0)所有者= centralMinter;
   }

中央造币厂

假设您要更改流通硬币的数量。当您的代币实际上代表一种区块链以外的资产(如金证或政府货币),并且您希望虚拟库存反映真实的资产时,就是这种情况。当货币持有者期望对代币价格有所控制,并希望发行或从流通中删除代币时,也可能是这种情况。

首先,我们需要添加一个变量来存储totalSupply并将其分配给构造函数。

合同MyToken {
       uint256 public totalSupply;

       函数MyToken(…){
           totalSupply =初始供应量;
           …
       }
       …
   }

现在,让我们最后添加一个新功能,该功能将使所有者能够创建新令牌:

function mintToken(address target,uint256 mintedAmount)onlyOwner {
       balanceOf [target] + = mintedAmount;
       totalSupply + = mintedAmount;
       转账(0,所有者,mintedAmount);
       转账(所有者,目标,mintedAmount);
   }

请注意,函数名称末尾的修饰符onlyOwner。这意味着此函数将在编译时重写,以从我们之前定义的修饰符onlyOwner继承代码。该函数的代码将插入在修饰符函数下划线的位置,这意味着该特定函数只能由设置为所有者的帐户调用。只需将其添加到拥有者修饰符的合约中,便可以创建更多硬币。

资产冻结

根据您的用例,您可能需要对谁可以使用令牌和不能使用令牌使用一些监管障碍。为此,您可以添加一个参数,使合同所有者可以冻结或取消冻结资产。

在合同内的任何位置添加此变量和函数。您可以将它们放置在任何位置,但是为了良好实践,我们建议您将映射与其他映射放置在一起,将事件与其他事件放置在一起。

映射(address => bool)public FrozenAccount;
   事件FrozenFunds(目标地址,布尔冻结);

   函数freezeAccount(地址目标,布尔冻结)onlyOwner {
       FrozenAccount [target] =冻结;
       FrozenFunds(目标,冻结);
   }

使用此代码,默认情况下所有帐户都不会冻结,但所有者可以通过调用“冻结帐户”将其中任何一个设置为冻结状态。不幸的是,冻结没有任何实际效果,因为我们没有在传递函数中添加任何内容。我们现在正在改变它:

函数传递(地址_to,uint256 _value){
       require(!frozenAccount [msg.sender]);

现在,任何冻结的帐户仍将保留其资金,但将无法动用它们。默认情况下,所有帐户都不会冻结,直到您冻结它们为止,但是您可以轻松地将该行为还原为白名单,您需要在其中手动批准每个帐户。只需将FrozenAccount重命名为核准的帐户,并将最后一行更改为:

require(approvedAccount [msg.sender]);

自动买卖

到目前为止,您已经依靠实用程序和信任来对令牌进行估价。但是,如果您愿意,可以通过创建一个以市场价自动买卖它们的基金,使令牌的价值得到Pirl(或其他令牌)的支持。

首先,让我们设定买卖价格:

uint256公开卖价;
   uint256公共购买价格;

   函数setPrices(uint256 newSellPrice,uint256 newBuyPrice)仅所有者{
       sellPrice = newSellPrice;
       buyPrice = newBuyPrice;
   }

对于价格变化不大的情况,这是可以接受的,因为每次新的价格变化都将要求您执行交易并花费一点Pirl。如果您希望获得固定的浮动价格,建议您调查标准数据Feed

下一步是购买和出售功能:

函数buy()应付收益(单位金额){
       金额=信息价值/购买价格; //计算金额
       require(balanceOf [this]> =数量); //检查是否有足够的销售
       balanceOf [msg.sender] + =金额; //将金额添加到买家的余额中
       balanceOf [this]-=金额; //从卖方的余额中减去金额
       汇款(此,msg.sender,金额); //执行一个反映更改的事件
       退货金额//结束函数并返回
   }

   函数Sell(单位金额)收益(单位收入){
       require(balanceOf [msg.sender]> = amount); //检查发件人是否有足够的销售能力
       balanceOf [this] + =金额; //将金额添加到所有者的余额中
       balanceOf [msg.sender]-=金额; //从卖方的余额中减去金额
       收入=金额* sellPrice;
       msg.sender.transfer(收入); //将Pirl发送给卖方:最后执行此操作以防止递归攻击很重要
       转账(msg.sender,这个,金额); //执行一个反映更改的事件
       收益; //结束函数并返回
   }

注意,这不会创建新令牌,但会更改合同拥有的余额。合同既可以拥有自己的代币和Pirl,又可以拥有合同的所有者,尽管它可以设置价格或在某些情况下创建新代币(如果适用),但它不能接触银行的代币或Pirl。该合同可以转移资金的唯一方法是出售和购买资金。

注意买卖的“价格”不是在Pirl中设置的,而是在系统中设置的最低货币(相当于欧元和美元中的美分,或比特币中的Satoshi)。一个Pirl是1000000000000000000 wei。因此,当在Pirl中为令牌设置价格时,请在末尾添加18个零。

创建合同时,向其发送足够的Pirl,以便它可以回购市场上的所有代币,否则您的合同将资不抵债,并且您的用户将无法出售其代币。

当然,前面的示例描述了与单个中央买家和卖家的合同,更有趣的合同将允许市场上任何人都可以出价不同的价格,或者也许它将直接从外部来源加载价格。

自动充值

每次您在Pirl上进行交易时,都需要向该区块的矿工支付费用,该费用将计算您的智能合约的结果。尽管这种情况将来可能会改变,但目前只能在Pirl中支付费用,因此您令牌的所有用户都需要使用。余额小于费用的帐户中的令牌会被卡住,直到所有者可以支付必要的费用为止。但是在某些用例中,您可能不希望用户考虑Pirl,区块链或如何获取Pirl,因此一种可能的方法是,一旦硬币中的余额达到危险的低水平,硬币就会自动补充用户的余额。

为此,首先需要创建一个将包含阈值量的变量和一个用于更改阈值的函数。

uint minBalanceForAccounts;

   函数setMinBalance(uint minimumBalanceInFinney)onlyOwner {
        minBalanceForAccounts = minimumBalanceInFinney * 1芬妮;
   }

 

然后,将此行添加到传递函数中,以便退回发件人:

  / *发送硬币* /
   函数传递(地址_to,uint256 _value){
       …
       if(msg.sender.balance <minBalanceForAccounts)
           sell((minBalanceForAccounts – msg.sender.balance)/ sellPrice);
   }

 

您也可以改为进行更改,以便发件人将费用支付给收件人:

  / *发送硬币* /
   函数传递(地址_to,uint256 _value){
       …
       如果(_to.balance            _to.send(sell((minBalanceForAccounts – _to.balance)/ sellPrice));
   }

这将确保没有任何接收令牌的账户具有少于支付费用所必需的Pirl。

工作证明

有一些方法可以将硬币供应与数学公式联系起来。最简单的方法之一就是与Pirl进行“合并采矿”,这意味着在Pirl上找到一个区块的任何人也会从您的硬币中获得奖励,因为有人在该区块上调用了奖励功能。您可以使用特殊关键字coinbase来做到这一点,该关键字指向找到该区块的矿工。

函数GiveBlockReward(){
       balanceOf [block.coinbase] + = 1;
   }

也可以添加一个数学公式,以便任何能做数学的人都能获得奖励。在下一个示例中,您必须计算当前挑战的立方根得到一个点,并有权设置下一个挑战:

uint currentChallenge = 1; //您能找出该数字的立方根吗?

   函数rewardMathGeniuses(uint answerToCurrentReward,uint nextChallenge){
       require(answerToCurrentReward ** 3 == currentChallenge); //如果答案错误,请不要继续
       balanceOf [msg.sender] + = 1; //奖励玩家
       currentChallenge = nextChallenge; //设置下一个挑战
   }

当然,虽然立方根的计算对某人来说很难,但使用计算器非常容易,因此该游戏很容易被计算机破坏。另外,由于最后一位获胜者可以选择下一个挑战,因此他们可以选择他们知道的somPirling,因此对其他玩家而言不是一个非常公平的游戏。有些任务对人类来说很容易,但对计算机来说却很难,但是通常很难用这样的简单脚本编写代码。取而代之的是,更公平的系统应该对计算机来说很难,但是对计算机来说并不是很难。最好的选择是创建一个哈希挑战,其中挑战者必须从多个数字生成哈希,直到他们找到一个低于给定难度的哈希为止。

该过程最初由Adam Back在1997年提出 哈希现金 然后由中本聪(Satoshi Nakamoto)在比特币中实现,作为2008年的工作量证明。

如果您喜欢将散列作为一种硬币的随机发行形式,则仍可以创建自己的具有工作证明的基于Pirl的货币:

bytes32 public currentChallenge; //硬币始于挑战
   uint public timeOfLastProof; //用来跟踪何时给予奖励的变量
   公共困难度= 10 ** 32; //难度开始相当低

   函数proofOfWork(uint随机数){
       bytes8 n = bytes8(sha3(nonce,currentChallenge)); //根据输入生成随机哈希
       require(n> = bytes8(难度)); //检查是否困难

       uint timeSinceLastProof =(现在– timeOfLastProof); //计算自上次获得奖励以来的时间
       require(timeSinceLastProof> = 5秒); //奖励不能太快
       balanceOf [msg.sender] + = timeSinceLastProof / 60秒; //对获胜者的奖励每分钟都在增加

       难度=难度* 10分钟/次SinceLastProof +1; //调整难度

       timeOfLastProof =现在; //重置计数器
       currentChallenge = sha3(立即,currentChallenge,block.blockhash(block.number – 1)); //保存将用作下一个证明的哈希
   }

还要更改Constructor函数(与合同同名的函数,该函数在第一次上载时会被调用)以添加此行,因此难度调整不会太疯狂:

timeOfLastProof =现在;

合同在线后,选择功能“工作量证明”,将您喜欢的号码添加到现时字段中,然后尝试执行。如果确认窗口显示红色警告“无法执行数据”,请返回并选择另一个数字,直到找到一个允许事务继续进行的数字:此过程是随机的。如果您找到一个,则自从给出最后一次奖励以来每经过一分钟,您将获得1个令牌,然后挑战难度将上下调整,以平均每次奖励10分钟为目标。

试图找到可以给您奖励的数字的过程称为“挖掘”:如果难度增加,则很难找到一个幸运数字,但始终很容易验证您是否找到了一个数字。

改良币

全币代码
如果添加所有高级选项,则最终代码应如下所示:

语用强度^ 0.4.16;

合同拥有{
   向公共所有者讲话;

   函数owner()public {
       所有者= msg.sender;
   }

   仅修饰符所有者{
       require(msg.sender == owner);
       _;
   }

   函数transferOwnership(address newOwner)onlyOwner public {
       owner = newOwner;
   }
}


语用强度^ 0.4.16;

合同拥有{
   向公共所有者讲话;

   函数owner()public {
       所有者= msg.sender;
   }

   仅修饰符所有者{
       require(msg.sender == owner);
       _;
   }

   函数transferOwnership(address newOwner)onlyOwner public {
       owner = newOwner;
   }
}

interface tokenRecipient {function receiveApproval(address _from,uint256 _value,address _token,字节_extraData)public; }

合约TokenERC20 {
   //令牌的公共变量
   字符串公共名称;
   字符串公共符号;
   uint8公共小数= 18;
   //强烈建议使用18位小数,避免更改它
   uint256 public totalSupply;

   //这将创建一个具有所有余额的数组
   映射(address => uint256)public balanceOf;
   映射(地址=>映射(地址=> uint256))公共津贴;

   //这会在区块链上生成一个公共事件,该事件将通知客户
   事件传输(地址从索引开始,地址从索引开始,uint256值);

   //这会通知客户有关消耗的金额
   事件刻录(地址从uint256值索引);

   /**
    *构造函数
    *
    *使用初始供应令牌向合同创建者初始化合同
    */
   函数TokenERC20(
       uint256 initialSupply,
       字符串tokenName,
       字符串令牌
   ) 上市 {
       totalSupply = initialSupply * 10 ** uint256(十进制); //用小数位数更新总供给
       balanceOf [msg.sender] = totalSupply; //为创建者提供所有初始令牌
       名称= tokenName; //设置显示名称
       符号= tokenSymbol; //设置用于显示目的的符号
   }

   /**
    *内部转帐,只能由本合同调用
    */
   函数_transfer(address _from,address _to,uint _value)内部{
       //防止传送到0x0地址。使用burn()代替
       require(_to!= 0x0);
       //检查发件人是否足够
       require(balanceOf [_from]> = _value);
       //检查溢出
       require(balanceOf [_to] + _value> balanceOf [_to]);
       //将其保存为将来的断言
       uint previousBalances = balanceOf [_from] + balanceOf [_to];
       //从发件人减去
       balanceOf [_from]-= _value;
       //将其添加到收件人
       balanceOf [_to] + = _value;
       转移(_from,_to,_value);
       //断言用于使用静态分析来查找代码中的错误。他们永远不会失败
       assert(balanceOf [_from] + balanceOf [_to] == previousBalances);
   }

   /**
    *转移令牌
    *
    *从您的帐户向`_to`发送`_value`令牌
    *
    * @param _to收件人的地址
    * @param _value发送的金额
    */
   函数传递(地址_to,uint256 _value)public {
       _transfer(msg.sender,_to,_value);
   }

   /**
    *从其他地址转移令牌
    *
    *以_from的形式将_value令牌发送到_to。
    *
    * @param _from发件人的地址
    * @param _to收件人的地址
    * @param _value发送的金额
    */
   函数transferFrom(address _from,address _to,uint256 _value)public return(布尔成功){
       require(_value <= allowance [_from] [msg.sender]); //检查津贴
       allowance [_from] [msg.sender]-= _value;
       _transfer(_from,_to,_value);
       返回true;
   }

   /**
    *设置其他地址的津贴
    *
    *允许_spender代表您花费的令牌数不超过_value令牌
    *
    * @param _spender授权使用的地址
    * @param _value他们可以花费的最大金额
    */
   函数批准(地址_spender,uint256 _value)公共
       回报(成功成功){
       allowance [msg.sender] [_ spender] = _value;
       返回true;
   }

   /**
    *设置其他地址的限额并通知
    *
    *允许_spender代表您花费的令牌不超过_value,然后对其执行ping操作
    *
    * @param _spender授权使用的地址
    * @param _value他们可以花费的最大金额
    * @param _extraData一些额外的信息发送到批准的合同
    */
   函数approveAndCall(地址_spender,uint256 _value,字节_extraData)
       上市
       回报(成功成功){
       tokenRecipient支出者= tokenRecipient(_spender);
       如果(批准(_spender,_value)){
           Experer.receiveApproval(msg.sender,_value,this,_extraData);
           返回true;
       }
   }

   /**
    *销毁令牌
    *
    *不可撤销地从系统中删除“ _value”令牌
    *
    * @param _value消耗的金额
    */
   函数burn(uint256 _value)公共返回(布尔成功){
       require(balanceOf [msg.sender]> = _value); //检查发件人是否足够
       balanceOf [msg.sender]-= _value; //从发件人减去
       totalSupply-= _value; //更新totalSupply
       刻录(msg.sender,_value);
       返回true;
   }

   /**
    *从其他帐户销毁令牌
    *
    *代表`_from`不可撤销地从系统中删除`_value`令牌。
    *
    * @param _来自发件人的地址
    * @param _value消耗的金额
    */
   函数burnFrom(地址_from,uint256 _value)公共返回(布尔成功){
       require(balanceOf [_from]> = _value); //检查目标余额是否足够
       require(_value <= allowance [_from] [msg.sender]); //检查津贴
       balanceOf [_from]-= _value; //减去目标余额
       allowance [_from] [msg.sender]-= _value; //减去发件人的津贴
       totalSupply-= _value; //更新totalSupply
       Burn(_from,_value);
       返回true;
   }
}

/******************************************/
/ *高级令牌从这里开始* /
/******************************************/

拥有MyAdvancedToken合同,TokenERC20 {

   uint256公开卖价;
   uint256公共购买价格;

   映射(address => bool)public FrozenAccount;

   / *这会在区块链上生成一个公共事件,该事件将通知客户* /
   事件FrozenFunds(目标地址,布尔冻结);

   / *使用初始供应令牌向合同创建者初始化合同* /
   函数MyAdvancedToken(
       uint256 initialSupply,
       字符串tokenName,
       字符串令牌
   )TokenERC20(initialSupply,tokenName,tokenSymbol)公共{}

   / *内部转帐,只能由该合同调用* /
   函数_transfer(address _from,address _to,uint _value)内部{
       要求(_to!= 0x0); //防止传送到0x0地址。使用burn()代替
       要求(balanceOf [_from]> = _value); //检查发件人是否足够
       要求(balanceOf [_to] + _value> balanceOf [_to]); //检查溢出
       require(!frozenAccount [_from]); //检查发件人是否冻结
       require(!frozenAccount [_to]); //检查收件人是否冻结
       balanceOf [_from]-= _value; //从发件人减去
       balanceOf [_to] + = _value; //将其添加到收件人
       转移(_from,_to,_value);
   }

   /// @notice创建`mintedAmount`令牌并将其发送到`target`
   /// @param目标接收令牌的地址
   /// @param mintedAmount它将收到的令牌数量
   函数mintToken(地址目标,uint256 mintedAmount)仅所有者公共{
       balanceOf [target] + = mintedAmount;
       totalSupply + = mintedAmount;
       转账(0,this,mintedAmount);
       转账(this,target,mintedAmount);
   }

   /// @notice`冻结?预防允许目标发送和接收令牌
   /// @param目标地址将被冻结
   /// @param Frozen冻结或不冻结
   函数freezeAccount(地址目标,布尔冻结)仅所有者公共{
       FrozenAccount [target] =冻结;
       FrozenFunds(目标,冻结);
   }

   /// @notice允许用户购买“ newBuyPrice” Pirl的代币并出售“ newSellPrice`Pirl的代币
   /// @param newSellPrice用户可以卖给合约的价格
   /// @param newBuyPrice用户可以从合同中购买的价格
   函数setPrices(uint256 newSellPrice,uint256 newBuyPrice)仅所有者公共{
       sellPrice = newSellPrice;
       buyPrice = newBuyPrice;
   }

   /// @notice通过发送Pirl从合约中购买代币
   函数buy()应付帐款公共{
       单价=味精价值/ buyPrice; //计算金额
       _transfer(this,msg.sender,amount); //进行转移
   }

   /// @notice出售`amount`代币进行合约
   /// @param待售代币数量
   函数Sell(uint256数量)public {
       require(this.balance> =金额* sellPrice); //检查合约是否有足够的Pirl来购买
       _transfer(msg.sender,this,amount); //进行转移
       msg.sender.transfer(金额* sellPrice); //将Pirl发送给卖方。重要的是要做到这一点,以避免递归攻击
   }
}

部署中

向下滚动,您将看到估计的部署成本。如果您愿意,可以更改滑块以设置较小的费用,但是如果价格太低于平均市场价格,则您的交易可能需要更长的时间才能提取。单击部署,然后输入密码。几秒钟后,您将被重定向到仪表板,在“最新事务”下,您将看到一行“正在创建合同”。等待几秒钟,让某人来接您的交易,然后您会看到一个缓慢的蓝色矩形,代表还有多少个其他节点已看到您的交易并确认了交易。确认的次数越多,您就越有可能确保已部署代码。

单击“管理”页面上的链接,您将获得世界上最简单的中央控制面板,您可以在其中使用新创建的货币进行任何操作。

在左侧的“从合同中读取”下,您可以免费使用所有选项和功能来从合同中读取信息。如果您的令牌具有所有者,它将在此处显示其地址。复制该地址并将其粘贴到“余额”中,它将显示给您任何帐户的余额(该余额也会自动显示在具有令牌的任何帐户页面上)。

在右侧的“写入合同”下,您将看到可用于以任何方式更改或更改区块链的所有功能。这些将花费汽油。如果创建了允许铸造新硬币的合同,则应具有一个名为“ Mint Token”的功能。选择它。

选择将在其中创建这些新货币的地址,然后选择金额(如果将小数设置为2,则在金额之后添加2个零以创建正确的数量)。在“执行”中,选择设置为所有者的帐户,将“ Pirl”量保留为零,然后按“ Execute”。

确认几次后,收款人余额将更新以反映新的金额。但是您的接收者钱包可能不会自动显示它:为了知道自定义令牌,钱包必须手动将它们添加到监视列表。复制您的令牌地址(在管理页面上,按复制地址),然后将其发送给您的收件人。如果还没有,则应该转到合同选项卡,按监视令牌,然后在其中添加地址。最终用户可以自定义显示的名称,符号和十进制数,特别是当它们具有名称相似(或相同)的其他标记时。主图标不可更改,用户在发送和接收令牌时应注意它们,以确保它们处理的是真实交易,而不是某些模仿令牌。

使用硬币

部署令牌后,它们将被添加到您监视的令牌列表中,总余额将显示在您的帐户中。为了发送令牌,只需转到“发送”选项卡,然后选择一个包含令牌的帐户。该帐户拥有的令牌将在“ Pirl”下列出。选择它们,然后键入要发送的令牌数量。

如果要添加其他人的令牌,只需转到“合同”选项卡,然后单击“监视令牌”。例如,要将Pirl Vortex令牌添加到您的监视列表,只需添加地址0x0489A975393A1cD0330740040141D702C35180cb

怎么办?

您刚刚了解了如何使用Pirl发行令牌,该令牌可以表示您想要的任何内容。但是您可以使用令牌做什么?例如,您可以使用代币来代表公司的股份,也可以使用中央委员会投票决定何时发行新代币来控制通货膨胀。您也可以通过众筹将其用于公益事业。接下来您要做什么?

参考资料:ethereum.org


订阅我们的新闻

获取更新并向最好的人学习

更多探索

Pirl和Vseed革新了医疗业务

Pirl和Vseed革新了医疗业务,Pirl很高兴宣布与合资企业Vseed建立长期合作伙伴关系。 Vseed将使用全部

zh_CN简体中文
en_USEnglish fr_FRFrançais nl_NLNederlands tr_TRTürkçe es_ESEspañol pt_PTPortuguês ru_RUРусский ko_KR한국어 hi_INहिन्दी zh_CN简体中文