function testSoulboundBypass() public {
vm.prank(alice);
nft.mintProfile("Alice", 25, "ipfs://alice");
uint256 tokenId = nft.profileToToken(alice);
vm.prank(alice);
nft.approve(bob, tokenId);
vm.prank(bob);
IERC721(address(nft)).transferFrom(alice, bob, tokenId);
assertEq(nft.ownerOf(tokenId), bob);
assertEq(nft.profileToToken(bob), tokenId);
}
- remove this code
+ add this code
/// @notice Override approve to prevent any approvals
function approve(address, uint256) public pure override {
revert SoulboundTokenCannotBeTransferred();
}
/// @notice Override setApprovalForAll to prevent operator approvals
function setApprovalForAll(address, bool) public pure override {
revert SoulboundTokenCannotBeTransferred();
}
/// @notice Override getApproved to always return zero address
function getApproved(uint256) public pure override returns (address) {
return address(0);
}
/// @notice Override isApprovedForAll to always return false
function isApprovedForAll(address, address) public pure override returns (bool) {
return false;
}
/// @notice Override transferFrom to prevent any transfer
function transferFrom(address, address, uint256) public pure override {
revert SoulboundTokenCannotBeTransferred();
}
/// @notice Override safeTransferFrom to prevent any transfer
function safeTransferFrom(address, address, uint256) public pure override {
revert SoulboundTokenCannotBeTransferred();
}
/// @notice Override safeTransferFrom with data to prevent any transfer
function safeTransferFrom(address, address, uint256, bytes memory) public pure override {
revert SoulboundTokenCannotBeTransferred();
}
/// @notice Override _update to prevent any transfer (internal safeguard)
function _update(address to, uint256 tokenId, address auth)
internal
override
returns (address)
{
address from = _ownerOf(tokenId);
// Allow minting (from == address(0))
if (from == address(0)) {
return super._update(to, tokenId, auth);
}
// Allow burning (to == address(0))
if (to == address(0)) {
return super._update(to, tokenId, auth);
}
// Prevent all other transfers
revert SoulboundTokenCannotBeTransferred();
}