You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Jan 12, 2025. It is now read-only.
In one vote period, if one NFT position reach lock time, the related MLUM tokens can be used to vote for twice.
Vulnerability Detail
In MlumStaking, stakers will stake MLUM tokens to mint one NFT position. Stakers can make use of the position NFT to vote for their pool.
In vote(), we add some check to check whether this NFT has the right to vote for one pool.
The vulnerability is that the input check is not enough. Considering that one NFT token's timelock reaches, we use this NFT to vote for one pool. And then we can withdraw from MlumStaking and recreate one position into MlumStaking to generate another NFT position. We can use this position to vote again.
We can use the same funds to vote twice.
functionvote(uint256tokenId,address[]calldatapools,uint256[]calldatadeltaAmounts)external{if(pools.length!=deltaAmounts.length)revertIVoter__InvalidLength();// check voting startedif(!_votingStarted())revertIVoter_VotingPeriodNotStarted();if(_votingEnded())revertIVoter_VotingPeriodEnded();// check ownership of tokenIdif(_mlumStaking.ownerOf(tokenId)!=msg.sender){revertIVoter__NotOwner();}uint256currentPeriodId=_currentVotingPeriodId;// check if alreay votedif(_hasVotedInPeriod[currentPeriodId][tokenId]){revertIVoter__AlreadyVoted();}// check if _minimumLockTime >= initialLockDuration and it is locked// @audit possible to vote twice with the same amount to mlumstakingif(_mlumStaking.getStakingPosition(tokenId).initialLockDuration<_minimumLockTime){revertIVoter__InsufficientLockTime();}if(_mlumStaking.getStakingPosition(tokenId).lockDuration<_periodDuration){revertIVoter__InsufficientLockTime();}
......
}
Poc
functiontestPocVoted()public{// Create position at firstvm.startPrank(ALICE);_createPosition(ALICE);vm.warp(3weeks);vm.prank(DEV);_voter.startNewVotingPeriod();vm.startPrank(ALICE);_voter.vote(1,_getDummyPools(),_getDeltaAmounts());// withdraw this NFT_pool.withdrawFromPosition(1,1ether);_stakingToken.approve(address(_pool),1ether);_pool.createPosition(1ether,2weeks);_voter.vote(2,_getDummyPools(),_getDeltaAmounts());vm.stopPrank();}
Impact
Stakers' voting power should be determined by staking behavior. Now malicious users can increase their voting power to get more pool rewards for their pool. This is unfair.
sherlock-admin4
changed the title
Future Mandarin Unicorn - Funds in MlumStaking may be used to vote twice
jennifer37 - Funds in MlumStaking may be used to vote twice
Jul 29, 2024
jennifer37
Medium
Funds in MlumStaking may be used to vote twice
Summary
In one vote period, if one NFT position reach lock time, the related MLUM tokens can be used to vote for twice.
Vulnerability Detail
In MlumStaking, stakers will stake MLUM tokens to mint one NFT position. Stakers can make use of the position NFT to vote for their pool.
In vote(), we add some check to check whether this NFT has the right to vote for one pool.
The vulnerability is that the input check is not enough. Considering that one NFT token's timelock reaches, we use this NFT to vote for one pool. And then we can withdraw from MlumStaking and recreate one position into MlumStaking to generate another NFT position. We can use this position to vote again.
We can use the same funds to vote twice.
Poc
Impact
Stakers' voting power should be determined by staking behavior. Now malicious users can increase their voting power to get more pool rewards for their pool. This is unfair.
Code Snippet
https://github.com/sherlock-audit/2024-06-magicsea/blob/main/magicsea-staking/src/Voter.sol#L153-L219
Tool used
Manual Review
Recommendation
If one NFT position wants to vote, we should make sure this NFT position is locked and cannot be unlocked before the vote period ends.
Duplicate of #166
The text was updated successfully, but these errors were encountered: