# Treasure DAO 攻击事件分析

By [xyyme.eth](https://paragraph.com/@xyyme) · 2022-03-25

---

前段时间，Treasure DAO 被[攻击](https://arbiscan.io/tx/0x37222d3ad371dff2d3f3ae1c788d1cc4ad69e9f1839776830726485119a89269)，造成市场上一部分的 NFT 可以被以 0 的价格买到。究其原因，其实是由于合约代码中一个很简单的 bug 造成的，这篇文章我们就来看看。

TreasureDAO 是一个 NFT 市场，其相关合约主要有两个（对应的地址均为当时攻击发生时的地址）：

*   [TreasureMarketplaceBuyer](https://arbiscan.io/address/0x812cda2181ed7c45a35a691e0c85e231d218e273#code) （1）
    
*   [TreasureMarketplace](https://arbiscan.io/address/0x2e3b85f85628301a0bce300dee3a6b04195a15ee#code) （2）
    

### 代码分析

先来看看 2 合约都有些什么方法：

*   createListing（NFT 上架）
    
*   updateListing（更新 NFT 相关商品信息）
    
*   cancelListing（下架）
    
*   buyItem（购买商品）
    
*   一些 set 函数设置一些参数
    

再来看看主要的 buyItem 方法：

![](https://storage.googleapis.com/papyrus_images/c0491a8423585b03413490ca7a84bff5e265701eaca057223b3158fa51d33ffe.png)

可以看到，购买 ERC1155 和 ERC721 是被放在一个方法中处理的。问题在于对于 1155 来说，tokenId 下的数量是有意义的，对于 721 来说，不存在数量这个字段（不熟悉 1155 的同学可以看看我之前写的[这篇文章](https://mirror.xyz/xyyme.eth/xCFB6NNV3PCPVju_4YQIImZEiyDp8SMlMBGT8pi_Pfw)）。这里放在一起处理，对于 1155 来说没有问题，但是对于 721 来说，如果正常传 1，那么也没有问题，但是如果传大于 1 的值，就可能会造成用户多付几倍的钱，却只买到了一个 NFT。如果传 0，那么就会造成零元购（我猜测项目方在开发时可能就内部约定，在 721 的情况下，前端默认传 1，没有考虑传 0 的情况）。

这里还有一个问题，攻击者是通过调用 1 合约的 buyItem 方法再进入到 2 合约中的，而 2 合约没有对 msg.sender 进行校验。不过，不能确定这是一个漏洞，还是项目方有意为之。由于我没有对项目整体合约架构进行阅读，因此对这里不做评价。

我们可以顺便来看看 1 合约的 buyItem 方法，同样没有对数量参数进行非零校验：

![](https://storage.googleapis.com/papyrus_images/4167a9032a4d9024ffe6a38acac1f8d240a58aaf1eb9eb1dc602ad1dbfabba7d.png)

我们再来看看 createListing （NFT 上架）方法：

![](https://storage.googleapis.com/papyrus_images/250daf8594e5b807786aadf237d18d8205e6d6ac6fe1636262018706e4e71598.png)

可以看到，\_quantity 参数仅仅对于 ERC1155 起作用，但是在最后的商品信息赋值时，却用到了这个参数。这里如果在上架 ERC721 的时候，数量传 1，没有问题，如果数量传大于 1 的值，就会造成数据紊乱。如果用户在购买的时候也传了大于 1 的值，就可能会多花冤枉钱，这就是我前面说的情况。

### 总结

造成这次攻击的原因主要在于没有对输入参数作完整的校验，这也是我们在日常开发中经常容易忽视的一点，不能仅仅考虑项目前端调用，还要考虑到有科学家会直接调用合约的情况。

还有就是代码中将 ERC721 和 ERC1155 放在一起处理，会造成一些逻辑混乱，这样就容易出现 bug，这种情况还是要避免。

### 参考

[![User Avatar](https://storage.googleapis.com/papyrus_images/6757df3e03f34d3e11d85491ddef9ec1796ce54e4807a57ece6c16c4f163c623.jpg)](https://twitter.com/peckshield)

[PeckShield Inc.](https://twitter.com/peckshield)

[@peckshield](https://twitter.com/peckshield)

[![Twitter Logo](https://paragraph.com/editor/twitter/logo.png)](https://twitter.com/peckshield/status/1499251425393582081)

2/ To illustrate, we use the above hack tx and show the key steps below:  
1\. Call buyItem() with valid NFT token and NFT ID, but w/ invalid ZERO quantity  
2\. Treasure Marketplace sells the NFT but charges ZERO MAGIC (due to ZERO quantity)

![](https://storage.googleapis.com/papyrus_images/8e38dbab35ec1000875b05e7f920efe38146f54928e736b78763f1a776afba54.jpg)

 [![Like Icon](https://paragraph.com/editor/twitter/heart.png) 15](https://twitter.com/peckshield/status/1499251425393582081)[

11:12 PM • Mar 2, 2022

](https://twitter.com/peckshield/status/1499251425393582081)

[https://www.tuoluo.cn/article/detail-10095262.html](https://www.tuoluo.cn/article/detail-10095262.html)

[

TreasureDAO攻击事件分析-安全KER - 安全资讯平台
--------------------------------

安全KER - 安全资讯平台

https://www.anquanke.com

![](https://storage.googleapis.com/papyrus_images/812af69f9a537c10cf532c46338d77049202b2d5aaf550500d7653a1330e0451.png)

](https://www.anquanke.com/post/id/269124)

---

*Originally published on [xyyme.eth](https://paragraph.com/@xyyme/treasure-dao)*
