0

用智能合约实现质押分红

 2 years ago
source link: https://learnblockchain.cn/article/3152
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

用智能合约实现质押分红

这两年DeFi的兴起,让世界看到了金融的另一种形式。越来越多的团队开始思考如何把传统的金融业务搬进区块链世界。

这两年DeFi的兴起,让世界看到了金融的另一种形式。越来越多的团队开始思考如何把传统的金融业务搬进区块链世界。区块链因其公开透明,不可篡改的性质,优势是显而易见的。然而一旦进来后才会发现区块链性能非常低效,同时与区块链交互又是非常昂贵的。所有区块链为了保证自身的正常运转,都设计了一套负反馈经济模型,典型的如以太坊的gas模型。许多看似简单的逻辑,用智能合约却很难实现。以前学过的算法和数据结构,在这里突然发现用不了了。也许我们需要新的思维,一种去中心化的思考方式。

废话不多说,我们这里就来分析一下常见的质押分红,这个功能怎么用智能合约实现。

质押分红是什么?

假设你开了一个网店,并发行了一种积分。用户购买商品的时候可以获得一定数量的积分。假设比例为1:100,1块钱的商品送100积分,积累的积分可以用来兑换商品。但是你不希望用户用积分来兑换你的商品,这是显然的。于是你设计了一个程序(智能合约),让用户自愿把他的积分质押起来,当然用户也可以在任何时候从智能合约中赎回属于自己的积分,就像我们在银行存钱一样。为了让用户自愿去质押,你修改了规则,将原来买1块钱商品可以获得100积分,现在改成了50积分,另外再将50积分按每个用户在智能合约中质押的积分比例分发给这些用。质押的积分越多,获得的积分也越多。购买的人越多,获得的积分也越多。积分有了利息,于是那些积分大户,纷纷把积分质押起来,赚取利息,并且还主动帮你推广网店。因为他们实际上已经成了网店的股东。

这个智能合约该怎么实现呢?

为了用智能合约实现,我们先把发行的积分token化,一个遵循ERC20标准的token。按照正常的思维,显然这个智能合约必须实现三个方法,也就是质押、赎回、分红。用户调用质押方法,将自己的token存入合约,合约中记录每个用户质押的token数量。用户通过赎回方法赎回之前质押的token。网店店主通过调用分红方法,传入用于分红的token,循环遍历所有质押的用户,按照质押数量比例分红。这里就有个问题,也就是前面提到的,区块链是昂贵的,里面不应该有大循环。因为gas费太高,甚至可能失败。所以我们应该思考一种没有循环的分红方式。

买过基金的童鞋们可能会发现,这里的质押跟买基金非常像。我们买入基金时,它会返回给你一定的份额。这个份额数量怎么来,就是用你买入的钱除以当前这只基金每份的价格。举个例子,假设有一只基金每份2元,你买入1000元,你将得到500份。过了一段时间,这只基金价格涨到了3元,你把手里的那500份卖掉得到1500元,赚了500。当然基金价格也有跌的时候,这时你卖掉就亏了。我们分析一下里面的逻辑,基金的价格怎么来。显然价格等于总价值除以总份额,价格是算出来的,只需记录基金的总价值和份额就可以了。我们买入基金时,总价值增加了,为了保证价格不变,份额也等比例增加了,这个比例就是价格。卖出时同理,份额减少,总价值等比例减少。为什么基金会有涨和跌,因为基金经理拿着基金的钱去投资,当然有赚有亏,也就是总价值变化 了,份额还是没变。

回到我们的质押分红合约,实际上就是一只基金,区别在于基金的钱是要拿去投资的,可能会亏损,而我们质押的token是躺在合约里面的。质押分红合约相当于一只只涨不跌的基金,质押相当于买入基金,赎回相当于卖出,分红就是把token转入合约,也就是总价值变大了。所以分红函数是不需要实现的,只需要往合约地址转账即可。

更进一步,我们还可以把份额设计成ERC20的token,命名为LP,这样LP也是可以转账的。所以核心的功能只剩下质押和赎回两个函数了。质押相当于铸造新的LP token,代码如下:

function mint(uint tokenAmount) public {
	 require(tokenAmount > 0, "invalid tokenAmount");
	
	 uint lpAmount = 0;
	 if (m_totalSupply == 0 || totalToken() == 0) {
		 lpAmount = tokenAmount;
		 m_balances[msg.sender] = lpAmount;
		 m_totalSupply = lpAmount;
		
	 }else {
		 lpAmount = m_totalSupply.mul(tokenAmount).div(totalToken());
		 m_balances[msg.sender] = m_balances[msg.sender].add(lpAmount);
		 m_totalSupply = m_totalSupply.add(lpAmount);
	 }
	 
	 require(IERC20(m_token).transferFrom(msg.sender, address(this), tokenAmount), "failed to Transfer token");
	 emit Mint(msg.sender, lpAmount, tokenAmount);
}

第一次质押时,发行的LP数量和传入的token一样,之后按等比例发行。

赎回相当于销毁LP token,代码如下:

function burn(uint lpAmount) public {
	 require(lpAmount > 0, "invalid lpAmount");
	 require(lpAmount <= m_balances[msg.sender], "lpAmount exceed range");
	   
	 uint tokenAmount = totalToken().mul(lpAmount).div(m_totalSupply);
	 
	 m_balances[msg.sender] = m_balances[msg.sender].sub(lpAmount);
	 m_totalSupply = m_totalSupply.sub(lpAmount);
	 
	 require(IERC20(m_token).transfer(msg.sender, tokenAmount), "failed to Transfer token");
	 
	 emit Burn(msg.sender, lpAmount, tokenAmount);
}

赎回的时候按等比例销毁LP即可。

总结一下

传统金融很多逻辑都是可以用区块链实现的,包括在电商行业流行的各种优惠券,积分券等等。相对于传统互联网方式,区块链的方式更透明,也更灵活。同时对于智能合约开发人员又提出了新的要求,不仅要会写代码,还有掌握一定的金融知识。用去中心化的思维,灵活运用。

完整的代码在github上面:

https://github.com/liyue201/stock-contract

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2小时前
  • 阅读 ( 33 )
  • 学分 ( 5 )
  • 分类:智能合约

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK