如何用Solidity编写一个锁池子智能合约?附代币锁仓开发代码教程
锁池大家都听过,就是将去中心化交易所的流动性资金池锁在智能合约里,短期内拿不出来,这样做的好处是防止项目方跑路。如果你的资金池不锁,大家就会觉得可能会存在风险。现在市场上主流的锁池方式不外乎两种,第一种是直接将LP代币打入黑洞,永久锁池。第二种就是使用粉红锁池、DXlock等第三方平台进行锁池。
关于锁池的详细介绍,可以看我另一篇文章:怎么看BSC薄饼的资金池锁了没有?怎么锁池?
用第三方平台锁池固然方便,但是缺乏安全性。万一锁池平台跑路了怎么办?万一人家那个锁池的合约有漏洞怎么办?基于这个问题,我们可以尝试自己开发一个锁池智能合约,这样既保证了安全性,又可以让用户放心。接下来,就给大家简单讲解一下,如何实现锁池智能合约的开发工作。
一、锁池的原理与LP代币的概念
在合约开发之前,我们需要了解一下:锁池的原理是什么,LP代币又是什么东西。
锁池,本质上就是将用户的LP代币锁在智能合约里一段时间,受益人在锁仓期满后可以取走LP代币。那LP代币其实是交易所给出的一个流动性凭证,当用户在去中心化交易所(比如博饼)创建了流动性之后,这个交易所会给予用户一些LP代币作为你撤出流动性的凭证。一旦LP代币被锁住,自然也无法撤出流动性,也就是说池子撤不了了。
二、代码实现锁池合约
下面,我们就写一个锁仓ERC20代币的锁池合约TokenLocker。它的逻辑很简单:
- 开发者在部署合约时规定锁仓的时间,受益人(锁池人的)地址,以及代币合约。
- 开发者将代币(或者说LP凭证)转入锁池合约。
- 在锁仓期满,受益人可以取走合约里的LP代币。
事件
锁池合约中共有2个事件。
- TokenLockStart:锁仓开始事件,在合约部署时释放,记录受益人地址,代币地址,锁仓起始时间,和结束时间。
- Release:代币释放事件,在受益人取出代币时释放,记录记录受益人地址,代币地址,释放代币时间,和代币数量。
// 事件 event TokenLockStart(address indexed beneficiary, address indexed token, uint256 startTime, uint256 lockTime); event Release(address indexed beneficiary, address indexed token, uint256 releaseTime, uint256
状态变量
TokenLocker合约中共有4个状态变量。
- token:锁仓代币地址。
- beneficiary:受益人地址。
- locktime:锁仓时间(秒)。
- startTime:锁仓起始时间戳(秒)。
// 被锁仓的ERC20代币合约 IERC20 public immutable token; // 受益人地址 address public immutable beneficiary; // 锁仓时间(秒) uint256 public immutable lockTime; // 锁仓起始时间戳(秒) uint256 public immutable startTime;
函数
TokenLocker合约中共有2个函数。
- 构造函数:初始化代币合约,受益人地址,以及锁仓时间。
- release():在锁仓期满后,将代币释放给受益人。需要受益人主动调用release()函数提取代币。
/** * @dev 部署时间锁合约,初始化代币合约地址,受益人地址和锁仓时间。 * @param token_: 被锁仓的ERC20代币合约 * @param beneficiary_: 受益人地址 * @param lockTime_: 锁仓时间(秒) */ constructor( IERC20 token_, address beneficiary_, uint256 lockTime_ ) { require(lockTime_ > 0, "TokenLock: lock time should greater than 0"); token = token_; beneficiary = beneficiary_; lockTime = lockTime_; startTime = block.timestamp; emit TokenLockStart(beneficiary_, address(token_), block.timestamp, lockTime_); } /** * @dev 在锁仓时间过后,将代币释放给受益人。 */ function release() public { require(block.timestamp >= startTime+lockTime, "TokenLock: current time is before release time"); uint256 amount = token.balanceOf(address(this)); require(amount > 0, "TokenLock: no tokens to release"); token.transfer(beneficiary, amount); emit Release(msg.sender, address(token), block.timestamp, amount);
三、合约部署实战演示
1. 先发币,给自己铸造10000枚代币。
2. 部署ToeknLocker锁池合约,代币地址为ERC20合约地址,受益人为自己,锁仓期填180秒。
3. 将10000枚代币转入合约。
4. 在锁仓期180秒内调用release()函数,无法取出代币。
5. 在锁仓期后调用release()函数,成功取出代币。
至此,一个简单的锁池合约就完成了。其实锁池和锁币是一个概念,锁池本质上也是锁定LP代币,所以这个合约也能用来进行代币锁仓。如果您要锁池,就填写LP代币的合约地址。如果您要锁币,就填写代币合约地址就可以了。
四、总结
合约的实现本身并不复杂,关键在于,这个合约是否能被用户信任。其实我们用第三方锁池平台的好处就是,用户认可,用户可以查询到,ave等数据平台也支持。如果是自己写合约锁仓的话,用户可能不接受。但是自己写合约,安全啊,安全才是最重要的,不是吗?大家如果有任何相关的技术需求,或者想要交流关于锁池的内容,欢迎找我。V信:btc6540,纸飞机tg:@btc6540