31281 - [SC - Low] Approved spender cannot withdraw or merge

Submitted on May 16th 2024 at 07:15:47 UTC by @OxAnmol for Boost | Alchemix

Report ID: #31281

Report type: Smart Contract

Report severity: Low

Target: https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/VotingEscrow.sol

Impacts:

  • Temporary freezing of NFTs

Description

Brief/Intro

Users who are approved, but do not own a particular NFT, are supposed to be eligible to call merge and withdraw from the NFT.

Currently, _burn(), used by merge() and withdraw() to remove the NFT from the system, will revert unless the sender is the owner of the NFT as the public approve called inside _burn requires the sender to be the owner or operator.

Vulnerability Details

The merge function and withdraw function is calling internal _burn

function merge(uint256 _from, uint256 _to) external {
        ...SNIP...
        _burn(_from, value0);
        _depositFor(_to, value0, end, _locked1.maxLockEnabled, _locked1, DepositType.MERGE_TYPE);
    }

Now if we have a look at _burn it calls the public approve function to set the token approval to address(0)

The main issue lies in this approve, which checks if the msg.sender is the owner and operator of the tokenId.

The approve function implementation itself is correct if the external users call it but in this case the merge and withdraw is also using the same function which causes the issue.

Note

The same issue was also submitted in the Velodrome c4 audit back in 2022. In that case, the problem was the same but the cause was different. https://github.com/code-423n4/2022-05-velodrome-findings/issues/66

Recommendation

Instead of calling approve it is recommended to set the approval to address(0) or delete it directly.

Impact Details

approved user is unable to execute ordinary operations due to a logic flaw which can freeze the NFT for them temporarily.

As per this impact i belive the high is appropriate according to severity guidelines which accounts Temporary freezing of NFT as High.

References

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L649

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L772

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L510

Proof of Concept

Paste this test inside VotingEscrow.t.sol. The test will pass on revert expectation as the merge is called by approved user.

Last updated

Was this helpful?