approve() and setApprovalForAll() Not Blocked on Soulbound TokensSoulboundProfileNFT.sol
The contract overrides transferFrom and safeTransferFrom to enforce soulbound behavior, but does NOT override approve() or setApprovalForAll(). Users can grant approvals on non-transferable tokens, emitting misleading Approval events.
Likelihood: High — Any token holder can call approve.
Impact: Low — No fund loss. Approvals are functionally useless since transfers revert. But misleading for integrating protocols and violates ERC-721 behavioral expectations.
Severity: Low
SWC: N/A
CWE: CWE-284 (Improper Access Control)
Evidence Grade: A
Alice mints a soulbound profile NFT. She then calls approve(bob, tokenId) to grant Bob approval over her token. The call succeeds and emits an Approval event, even though the token can never actually be transferred. She can also call setApprovalForAll(bob, true) to grant Bob operator status across all her tokens. Both approvals are accepted and stored on-chain despite being functionally useless.
forge test --match-test test_FINDING007_approve_not_blocked -vvvv → PASS
For a soulbound token, all transfer-related operations should be blocked — not just the transfers themselves, but also the approvals that precede them. Overriding approve() and setApprovalForAll() to revert with the same custom error used by transferFrom ensures consistent behavior: no approval can be set, no misleading events are emitted, and integrating protocols receive an immediate signal that this token is non-transferable.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.