ERC314是什么?怎么这么火...

ERC314的技术原理分析和源码解读

最近经常有人问我314怎么样,就连找我承接合约开发项目的都是ERC314相关的,趁着我现在开发项目,我把ERC314的基本原理讲解一下,供你参考,也作为我的一个工作记录。

先了解下ERC314的背景

2024年3月20日晚上,ERC314协议代币SIMP上线。此前,该项目募资20ETH,代币总量100万枚,并按照45%用于LP,45%给种子轮预售者,10%用于多签的 CEX钱包的比例进行分配。至此,你方唱罢我登场,与此相关的代币层出不穷,比如 LONG314、X314、BTC314、T314...),一度把价格炒到了千余倍,大有当年NFT的热度。

那么,ERC314到底有什么创新呢?我们扒开它的源码一步步来看下。

ERC314接口分析

先来看它的一组接口:

function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
function getReserves() public view returns (uint256, uint256)
function addLiquidity(uint32 _blockToUnlockLiquidity) public payable 
function removeLiquidity() public
function extendLiquidityLock(uint32 _blockToUnlockLiquidity) public
function getAmountOut(uint256 value, bool _buy) public view returns (uint256) 

咦?这不是跟ERC20很像吗?确实很像,实际上就是对ERC20的功能扩展,实现了类似uniswap的功能。比较粗暴但不够准确的理解就是 ERC314 = ERC20 + uniswap,接下来我们深入细节,看看究竟......

以下这些接口方法和ERC20一模一样,不再讲解,读者可自行看ERC20的标准
name, symbol, decimals, totalSupply, balanceOf, approve, allowance

ERC314核心流程

注意:下面都是以BNB链为例来说明问题

我认为,ERC314最核心的创新是改变了ERC20的转账模型,增加了两个内部方法:

  • buy 向合约转入BNB,得到314代币
  • sell 向合约转入314代币,得到BNB

在源码中,也就是transfertransferFrom这两个方法逻辑变了,每当to地址是代币合约时,就不再是普通转账了,如下所示:

function transfer(address to, uint256 value) public virtual returns (bool) {
   if (to == address(this)) {
      sell(_msgSender(), value);
   } else {
      _transfer(_msgSender(), to, value);
   }
   return true;
}

_transfer和ERC20一样是普通的转账,没什么可说的。sellbuy的内部细节下面再说,先从整体上把流程弄懂,再深究细节更容易理解。总之,核心思想就是,一个ERC314合约,就是一个 BNB / 314代币 的交易对池子,可直接完成swap交换。也许你会问,在uniswap交换不好吗?确实是,在uniswap有许许多多的交易对池子,可以跟多种币进行swap,这一点314确实没有优势。但是在节省gas这方面,ERC314不需要每次授权,也就是说,每次swap都比uniswap少了一笔交易,进而节省了gas费。实际上,ERC314之所以会出现,也是因为要省略DEX等中间环节节省gas

ERC314流动性提供

好了,现在又有另一个问题,既然是交易对池子,那用于swap的BNB和314代币哪里来?即流动性从哪里来?

这就涉及了上面的3个接口方法:

  1. addLiquidity:添加流动性
  2. removeLiquidity:移除流动性
function addLiquidity(uint32 _blockToUnlockLiquidity) public payable onlyOwner {
   require(liquidityAdded == false, "Liquidity already added");

   liquidityAdded = true;

   require(msg.value > 0, "No ETH sent");
   require(block.number < _blockToUnlockLiquidity, "Block number too low");

   blockToUnlockLiquidity = _blockToUnlockLiquidity;
   liquidityProvider = _msgSender();

   emit AddLiquidity(_blockToUnlockLiquidity, msg.value);
}

function removeLiquidity() public onlyLiquidityProvider {
   require(block.number > blockToUnlockLiquidity, "Liquidity locked");

   liquidityAdded = false;

   payable(liquidityProvider).transfer(address(this).balance);

   emit RemoveLiquidity(address(this).balance);
}

通过源码可以看到,这里的流动性符合3个特征:

  • 只有Owner可以提供
  • 提供的流动性会锁定一个期限(只有到了解锁区块号:blockToUnlockLiquidity 以后,才能移除流动性)
  • 在锁定期限内,只能提供一次流动性

相信你已经看出来了,在流动性提供这方面,是不是很有中心化的味道?和uniswap允许任何人提供流动性赚取收益不一样,这只能项目方提供流动性赚取收益。当然除了收益,提供流动性也是有风险的,下面讲到sell方法的时候,你就能体会这一点。

  1. extendLiquidityLock:扩展流动性锁定期限
function extendLiquidityLock(uint32 _blockToUnlockLiquidity) public onlyLiquidityProvider {
   require(blockToUnlockLiquidity < _blockToUnlockLiquidity, "You can't shorten duration");

   blockToUnlockLiquidity = _blockToUnlockLiquidity;
}

流动性提供者还可以将锁定期限延长,注意是只能延长,不能缩短。

ERC314价格预测与储备金

getAmountOutgetReserves 是获取当前交易对池子的价格和储备金的。

  1. 获取储备金
function getReserves() public view returns (uint256, uint256) {
   return (address(this).balance, _balances[address(this)]);
}

可以看到,获取储备金方法返回了当前代币合约的BNB数量314代币数量

  1. 获取交易价格
function getAmountOut(uint256 value, bool _buy) public view returns (uint256) {
   (uint256 reserveETH, uint256 reserveToken) = getReserves();

   if (_buy) {
      return (value * reserveToken) / (reserveETH + value);
   } else {
      return (value * reserveETH) / (reserveToken + value);
   }
}

价格是根据当前储备金数量实时计算的,这个公式可以说是swap的核心了,下面将要说的sell和buy方法也是根据此公式计算价格并完成交易的。

如果你研究过uniswap的价格预言机机制,你应该能想到,这里会不会有价格操纵风险?也就是先大量卖出314代币使得代币价格降低,从而获得一个便宜的价格。在ERC314里,技术上这个风险确实存在,但是在业务上,代币持有者好像也没有动力这么做吧?如果是uniswap上,获得便宜的价格之后还可以与其他币进行swap获利,但是这里只有一个交易对池子,好像也没啥必要这么做? 如果你看到了这里,也欢迎你来一起讨论,发到留言区,分享你的想法。

ERC314卖出与买入

  1. sell方法实现卖出
function sell(address owner, uint256 amount) internal {
   require(liquidityAdded, "Trading not enable");
   require(_msgSender() == tx.origin, "Only external calls allowed");

   uint256 ethAmount = (amount * address(this).balance) / (_balances[address(this)] + amount);

   require(ethAmount > 0, "Sell amount too low");
   require(address(this).balance >= ethAmount, "Insufficient ETH in reserves");

   _transfer(owner, address(this), amount);
   payable(owner).transfer(ethAmount);

   emit Swap(owner, 0, amount, ethAmount, 0);
}

sell方法其实逻辑挺简单的,就是根据用户转入的 314代币数量 计算出 能够兑换的BNB数量,然后把代币转入合约储备金,再从合约储备金里把BNB转给用户。

由于整个过程没有任何限制,所以这里的最大风险是314代币大户,如果一个大户持有者一次性卖出全部的代币,换出大量的BNB,你也毫无办法。这个大户也包括项目方哦。因此,项目方也害怕大户砸盘,你也害怕项目方卷款跑路,是不是很有趣?哈哈...

为了避免大户砸盘,我们可以将这个卖出的方法加一些限制,比如一次卖出不能超过储备金的20%等等,可以在一定程度上避免这种情况发生。

  1. buy方法实现买入
function buy() internal {
   require(liquidityAdded, "Trading not enable");
   require(_msgSender() == tx.origin, "Only external calls allowed");

   address owner = _msgSender();

   uint256 tokenAmount = (msg.value * _balances[address(this)]) / (address(this).balance);

   _transfer(address(this), owner, tokenAmount);

   emit Swap(owner, msg.value, 0, 0, tokenAmount);
}

buy方法更简单,根据转入的BNB数量,计算出可以兑换的314代币数量,收取BNB,转出314代币。

注意,收取BNB是通过下面这种方式进行的:

receive() external payable {
   buy();
}

至此,ERC314的技术分析已经讲完了。我做个总结,ERC314这个协议不是经过以太坊社区审核通过的协议,而是由最开始提到的那些项目自发组织和发行推广而被大众知道的,目前还在发展中,如果想发展的好,我认为还需要对这个协议再升级,再改版。核心就是控制风险,当然,相比于uniswap那些DEX,这个ERC314门槛比较低,更加中心化,对小白用户友好,不需要很复杂的学习过程,这都是它的优势。作为合约开发者,我们主要学习技术,其他的我也不懂,本人不炒币。

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

0 条评论

请先 登录 后评论
认知那些事
认知那些事
0x2b62...95a0
人立于天地之间,必然有我们的出路。