// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
import "forge-std/Test.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract VulnerableERC721 is ERC721, Ownable {
constructor() ERC721("MyNFT", "MNFT") {}
//custom transferFrom function which missing NFT owner check.
function transferFrom(
address from,
address to,
uint256 tokenId
) public override {
// direct transfer
_transfer(from, to, tokenId);
}
function safeMint(address to, uint256 tokenId) public onlyOwner {
_safeMint(to, tokenId);
}
}
batchFillOrder
函数中的 erc721.safeTransferFrom
调用。forge.exe test --contracts ./srctestNFT-transfer.sol -vvvv
function testVulnerableERC721() public {
VulnerableERC721Contract.ownerOf(1);
vm.prank(bob);
VulnerableERC721Contract.transferFrom(address(alice), address(bob), 1);
console.log(VulnerableERC721Contract.ownerOf(1));
}
可以看到代币的归属发生了变化
![DeFiVulnLabs靶场全系列详解(四十三)ERC721 NFT 未经授权的被转移]()
而如果是fixed的合约则提示未经授权
![DeFiVulnLabs靶场全系列详解(四十三)ERC721 NFT 未经授权的被转移]()
04
—
如何修复该问题
只需要require ERC721标准里的_isApprovedorOwner 即可
function transferFrom(address from, address to, uint256 tokenId) public override {
require(
_isApprovedOrOwner(_msgSender(), tokenId), // ✅ 检查调用者权限
"ERC721: caller is not token owner or approved"
);
_transfer(from, to, tokenId); // 再调用父合约的 _transfer
}
05
—
感谢关注
个人语雀账号:https://www.yuque.com/iceqaq
原文始发于微信公众号(Ice ThirdSpace):DeFiVulnLabs靶场全系列详解(四十三)ERC721 NFT 未经授权的被转移
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论