如何通过用于工厂模式来减低这个bug?‘亚博app’

  • 时间:
  • 浏览:3009
  • 来源:亚博app
本文摘要:智能合约可以部署其他智能合约。

智能合约可以部署其他智能合约。这使工厂模式沦为有可能,在工厂模式中,您可以创立多个智能合约,每个智能合约只追踪一件事,而不是一个追踪许多事情的智能合约。

用于此模式可以修改代码并增加某些类型的安全漏洞的影响。在这篇文章中,我将向您讲解一个基于我们在最近的审核中找到的一个关键漏洞的示例。如果用于了工厂模式,那么漏洞就就增加了很多。越野车智能合约下面是一个智能合约,通过一个非常非常简单的界面销售WETH。

如果您有WETH,你只必须批准后这个智能合约出售你的代币,它将保证你获得准确的金额缴纳。只要批准后充裕的代币,任何人都可以给定出售WETH。合约用于付款模式将缴付交付给卖方,但合约的作者罪了一个相当严重的错误:1// Technically this could sell any token, but we're selling WETH in this2// example because then I don't have to think about prices. 1 WETH costs 1 ETH.3contract WETHMarket {4IERC20 public weth;5mapping(address = uint256) public balanceOf;67constructor(IERC20 _weth) public {8weth = _weth;9}1011// Buy WETH from a specified seller. Seller must first approve WETH.12function buyFrom(address seller) external payable {13balanceOf[seller] += msg.value;14require(weth.transferFrom(seller, msg.sender, msg.value),15"WETH transfer failed.");16}1718// Used by a seller to get their ETH. 19function withdraw(uint256 amount) external {20require(amount = balanceOf[msg.sender], "Insufficient funds.");2122// Whoops! Forgot this:23// balanceOf[msg.sender] -= amount;2425(bool success, ) = msg.sender.call.value(amount)("");26require(success, "ETH transfer failed.");27}28}(如果您想要告诉为什么代码用于.call而不是.transfer,请求读者“立刻停止使用Solidity的传输()”)。

因为卖方的余额未曾增加,所以不出任何以太的卖方都可以重复调用withdraw()来消耗每个人的合约。这是一个相当严重的漏洞。修缮这个bug,就像大多数bug一样,一旦你找到了它,就显得微不足道了。

但在这篇文章中,我想要谈谈如何通过用于工厂模式来减低这个bug,即使我们不告诉这个特定的问题。现在让我们看一下更加非常简单的WETHMarket合约版本。

在这个版本中,合约只负责管理销售一个卖家的WETH。此合约与先前版本具备完全相同的bug:1contract WETHSale {2IERC20 public weth;3address seller; // only a single seller4uint256 public balance; // no need for a mapping anymore5 6constructor(IERC20 _weth, address _seller) public {7weth = _weth;8seller = _seller;9}1011// No need to specify the seller.12function buy() external payable {13balance += msg.value;14require(weth.transferFrom(seller, msg.sender, msg.value));15}16 17function withdraw(uint256 amount) external {18require(msg.sender == seller, "Only the seller can withdraw.");19require(amount = balance, "Insufficient funds.");2021uint256 amount = balance;22 23// Whoops! Forgot this:24// balance -= amount;25 26(bool success, ) = msg.sender.call.value(amount)("");27require(success, "ETH transfer failed.");28}29}尽管不存在完全相同的逻辑错误,但此漏洞并不是那么相当严重。只容许一个帐户调用withdraw(),并且合约中存储的所有以太网都归属于该帐户。

这个错误的影响只是余额并无法体现合约中的现实余额。这个bug是手工挑选出来表明其优点的,但是这个bug代表了托管地协议中的众多类bug。

根据我审核智能合约的经验,这是找到关键漏洞最少见的地方之一。托管地背后的点子是,有所不同的资金必需分离存放在,以保证合约一直可以涵括所有欠款。

取得托管地权最简单的方法之一是将资金几乎分为有所不同的智能合约。您可以将工厂模式看做是一种了解防卫的托管地方法。

非常简单代码单卖方版本的合约不仅有更加强劲的代管,而且更加非常简单。我们去除了一个函数参数和一个同构。

在生产代码中,我们可能会更进一步,几乎移除balance,而取而代之address(this).balance。因为我写出合约是为了便利读者,原本的代码早已很非常简单了。在现实世界的例子中,这种差异有可能更加明显。

从安全性的角度来看,任何减少复杂性的机会都是一种胜利。工厂模式每个卖家都可以部署自己的Wethsale合约并从非常简单的合约中受益,但是这种方法有一个主要的缺点,蓄意卖家可能会部署略为改动过的代码版本,但实质上并没传输weth。

即使像ConsenSys Diligence这样有信誉的公司审查了WETHSale代码,每个买家也必需检验他们出售的明确合约否用于了那些清楚的代码。用于工厂可以解决问题这个问题。工厂保证每个部署的合约都用于完全相同的代码,并且它获取了一个非常简单的查询机制来查询等价卖方的单一合约:contract WETHSaleFactory {IERC20 public weth;mapping(address = WETHSale) public sales;constructor(IERC20 _weth) public {weth = _weth;}function deploy() external {require(sales[msg.sender] == WETHSale(0), "Only one sale per seller.");sales[msg.sender] = new WETHSale(weth, msg.sender);}}潜在缺失用于工厂模式的一个主要缺点是价格昂贵。CREATE操作码目前的燃气成本为32,000。

我们的类似合约还必须另外两个SSTORE来追踪WETH和卖方地址,每个地址必须20,000燃气。这比代码的完整多卖家版本最少多72,000气体。另一个潜在的缺点是复杂性。

在大多数实际情况下,工厂模式修改了现有的合约,网卓新闻网,但请求忘记,它还加到了一个新的合约:工厂本身。根据代码的有所不同,这可能会造成复杂性的减少。在要求工厂模式之前,请求细心考虑到更改的总体影响。

总结1. 托管地方面的错误是造成关键漏洞的一个最重要原因。2. 用于分开的智能合约可以减少这些错误的严重性。3. 工厂模式以一种不能信任的方式构建了这一点。

4. 在使用工厂模式之前还要考虑到潜在的缺点。


本文关键词:卖方,智能合约,工厂,合约,代码,亚博app

本文来源:亚博app-www.ehnesorganic.com