教程 | 简易锁定合约:Part 2

Ajian   |     |   2150 次阅读

Saint Hodl之歌

无为在我们看来是一种明智之举。不论是我们还是大多数企业管理人员做梦都没想过会因为美联储将小幅调整贴现率的预测,亦或是某个华尔街大鳄对市场扭转了看法就狂热地卖出高盈利的子公司。那么,作为这些大企业的小额投资者,我们为何要有不同的表现? — Warren Buffet(沃伦·巴菲特)

在该系列的第一部分,我们了解了有条件地锁定合约允许双方在以太坊区块链上进行交易,使用哈希函数加密的密码让交易资金可以接受大众监督,并在将来进行检索。在本文中,我们要向用户介绍如何将代币发送给合约保管至将来的某个时间点。用加密货币交易术语来说就是“Hodling”,这通常而言是投资的最优策略(参见Warren Buffet之言)。

Hodl的来历

在2013年,一个名为 GameKyuubi 的用户发布了一篇如今臭名昭著的酒后写的荒唐文章,讲述了他作为一名交易者的悲惨遭遇——《I AM HODLING》

GameKyuubi 深知作为一名价值型投资者长期持有资产的重要性。然而,这类投资者在面对唾手可得的交易选择之时意志不够坚定。通过这个例子,我们将构建能让区块链为我们解决“Hodling(坚持长期持有)”这个难题的链式码。


Saint Hodl合约

Saint Hodl
              '-._   ```"""---.._
           ,-----.:___           `\  ,;;;,
            '-.._     ```"""--.._  |,%%%%%%              _
            ,    '.              `\;;;;  -\      _    _.'/\
          .' `-.__ \            ,;;;;" .__{=====/_)==:_  ||
     ,===/        ```";,,,,,,,;;;;;'`-./.____,'/ /     '.\/
    '---/              ';;;;;;;;'      `--.._.' /
   ,===/                          '-.        `\/
  '---/                            ,'`.        |
     ;                        __.-'    \     ,'
jgs  \______,,.....------'''``          `---`

太长不看版

先托管资金,之后再取回。以下所有合约都可以在 SaintHodl.com 上使用,不仅容易访问,在 github 上还可获得其开源资源。你可以使用你的 Jaxx.ioMEW 或是任意ETC钱包免费与之交互!

最重要的部分

时间锁定合约无法提前解锁。你无法和区块链协商,因此锁定的资金能够被安全地藏起来,直到通过了预定量的区块。而且不容反悔。

因此,在时间锁定合约(TLC)中,这一变量(按:锁定的区块时间)被公开列在了第一位。任何查看该合约的人很容易就能看到这一数字,预先知道他们的进程。在sainthodl 合约中,这条代码是这么写的:

uint public freezeBlocks = 20;

上述代码将合约的时间锁定了20个区块时间,也就是大约280秒,即4.67分钟。虽然时间不长,但是足够用来测试了。(如果你想要更多的话,这里还有200万个区块时间的选择 ;))

1-锁定区块如上图所示-

Lockers

在第一部分,我们提到哈希盒子是公开可见的。时间锁定合约同样会是如此。每个“盒子(Locker)”都将包括三个细节:拥有者、持有代币时间、持有代币数量。

struct locker{      
    uint freedom;
    uint bal;    
}    
mapping (address => locker) public lockers;

每个地址都将映射到一个独特的Locker上。

向Locker发送资金

何人在何时向我们的时间锁定合约发送代币,我们都想让该合约将资金添加进Locker并将时间锁定在将来的某个区块。我们将利用 solidity合约的回退函数实现这一设想:

function() payable public {        
    locker storage l = lockers[msg.sender];
    l.freedom =  block.number + freezeBlocks; 
    l.bal = l.bal + msg.value;
   }

Locker 是通过用户发送资金确认的(上述代码中,locker “l” 是信息发送者的locker)。之后,我们将最新的区块量(block.number)加上锁定区块的预定量,就是我们的“重归自由区块(freedom block)”。locker 的余额可以通过当前余额(通常是0)以及随信息一起发送过来的值计算出来。如果你通过 MyEtherWallet.com 使用 the github 上的abi,你就能看到locker内的一切东西了(余额将以Wei为单位)。

2-使用Mew合约界面-

重点二:取款

最后,随着恐慌性抛售的冲动过去之后,你就可以得到信任,取回你的资金了。在哈希锁合约中,任何持有私钥的人都可以索取资金,时间锁定合约则不同,只有 Locker 的拥有者才能取出他们的资金。要注意的是,在允许陌生人从合约中取走资金之时,避免开放递归调用很重要。Dao合约因其设计缺陷而失败了。如果将合约中的回退函数也设置成调用取款函数,人们再从合约中调用取款函数的话就行得通了。为了避免出现这种问题,我们在发送任意资金之前会将盒中的余额设置成0;这样的话,如果合约被调回,就不会取出资金了。

function withdraw() public { 
    locker storage l = lockers[msg.sender]; 
    require (block.number > l.freedom && l.bal > 0);
   // avoid recursive call 
    uint value = l.bal; 
    l.bal = 0; 
    msg.sender.transfer(value); 
}

与第一个函数相似,locker “l” 是信息发送者的 locker。之后,我们要求当前区块数量大于盒子内自由区块的数量,且盒子内的余额大于0。如果有任一条件未满足,该函数就会“失败”,也就是说不执行任何操作。如果两个条件都满足了,盒子内的余额就会存储为“值”。初始余额就会被设置为0,之后会将值发送给locker的所有者。

3-Mew上的取款函数-

事件

如果你浏览一遍合约,你会注意到出现了两个“事件”。

event Locked(address indexed locker, uint indexed amount);    
event Released(address indexed locker, uint indexed amount);

这两个事件会显示在等待事件的钱包中,可以用来触发发布推文等事件。

4-在Parity上看到的合约-

结束语

有了这个简易合约,任何人都可以将代币托管在区块链上,想托管多久就多久,过后再取回。第三部分将结合前两部分的函数创建一个哈希时间锁定合约来做些炫酷的事!


原文链接: https://medium.com/@DontPanicBurns/simple-locking-contracts-part-2-23afb841120f
作者: Cody Burns
翻译&校对: 闵敏 & Elisa

本文由作者授权 EthFans 翻译及再出版。


简易锁定合约系列:
Part-1


你可能还会喜欢:

科普 | Raiden Network — Ethereum 区块链支付通道
从技术角度剖析针对THE DAO的攻击手法
教程 | 以太坊编程简单介绍 ,Part-1

 
0 人喜欢