As can be seen from above that if msg.sender is approved i.e _spender == idToApprovals[_tokenId] then it is allowed to call _burn function.
But when approve(address(0), _tokenId); is called it reverts because it only allows if spenderIsOwner or spenderIsApprovedForAll not if spenderIsApproved as can be seen from the following function
function approve(address _approved, uint _tokenId) public {
address tokenOwner = idToOwner[_tokenId];
// Throws if `_tokenId` is not a valid NFT
require(tokenOwner != address(0));
// Throws if `_approved` is the current owner
require(_approved != tokenOwner);
// Check requirements
bool senderIsOwner = (idToOwner[_tokenId] == msg.sender);
bool senderIsApprovedForAll = (ownerToOperators[tokenOwner])[msg.sender];
require(senderIsOwner || senderIsApprovedForAll);
// Set the approval
idToApprovals[_tokenId] = _approved;
emit Approval(tokenOwner, _approved, _tokenId);
}
Impact
Approved spender can not call _burn function thus causes this functionality to be redundant as _burn is called in withdraw function as well as merge function.
Varun_19
Medium
_burn function will always revert even if the caller is the approved spender
Summary
_burn function will always revert even if the caller is the approved spender
Vulnerability Detail
Following is _burn function
As can be seen from above that if msg.sender is approved i.e _spender == idToApprovals[_tokenId] then it is allowed to call _burn function. But when approve(address(0), _tokenId); is called it reverts because it only allows if spenderIsOwner or spenderIsApprovedForAll not if spenderIsApproved as can be seen from the following function
Impact
Approved spender can not call _burn function thus causes this functionality to be redundant as _burn is called in withdraw function as well as merge function.
Code Snippet
https://github.com/sherlock-audit/2024-06-velocimeter/blob/main/v4-contracts/contracts/VotingEscrow.sol#L543
Tool used
Manual Review
Recommendation
Instead call _clearApproval function.
Duplicate of #42