CTF-ntf-bonanza
题目源代码:点击
要求是:新的 NFT 交易合约 BonanzaMarketplace 已经推出,它允许交易选定的白名单 ERC721 和 ERC1155 代币。您的挑战是获得所有列出的 NFT。
根据源码,可以发现此时的NTF都是ERC721代币,所以了解ERC721非同质化代币标准,会很好的理解。
要获得所列的NTF,就先看看,buyItem函数
function buyItem( address _nftAddress, uint256 _tokenId, address _owner, uint256 _quantity ) external nonReentrant isListed(_nftAddress, _tokenId, _owner) validListing(_nftAddress, _tokenId, _owner) { require(_msgSender() != _owner, "Cannot buy your own item");
Listing memory listedItem = listings[_nftAddress][_tokenId][_owner]; require(listedItem.quantity >= _quantity, "not enough quantity");
// Transfer NFT to buyer if (IERC165(_nftAddress).supportsInterface(INTERFACE_ID_ERC721)) { IERC721(_nftAddress).safeTransferFrom(_owner, _msgSender(), _tokenId); } else { IERC1155(_nftAddress).safeTransferFrom(_owner, _msgSender(), _tokenId, _quantity, bytes("")); }
if (listedItem.quantity == _quantity) { delete (listings[_nftAddress][_tokenId][_owner]); } else { listings[_nftAddress][_tokenId][_owner].quantity -= _quantity; }
emit ItemSold( _owner, _msgSender(), _nftAddress, _tokenId, _quantity, listedItem.pricePerItem );
_buyItem(listedItem.pricePerItem, _quantity, _owner); }
function _buyItem( uint256 _pricePerItem, uint256 _quantity, address _owner ) internal { uint256 totalPrice = _pricePerItem * _quantity; uint256 feeAmount = totalPrice * fee / BASIS_POINTS; IERC20(paymentToken).safeTransferFrom(_msgSender(), feeReceipient, feeAmount); IERC20(paymentToken).safeTransferFrom(_msgSender(), _owner, totalPrice - feeAmount); }
|
从上我们可以看到,并没有对购买数量quantity的检查,所以即使购买零个NTF也是可以的,重点来了,在ERC721代币标准中,对于购买数量并没有要求,还是会发送tokenId给购买者,这就是漏洞所在
攻击思路:直接调用buyItem函数,购买零个ERC721代币标准的NTF就可以了
个人认为,这个题就是疏忽了ERC721代币的执行标准,所以对于一些主流协议,还是必须的了解。