-
Notifications
You must be signed in to change notification settings - Fork 6
cocacola - Voting does not take into account end of staking lock period #166
Comments
The protocol team fixed this issue in the following PRs/commits: |
Escalate Some issues have been incorrectly duped with this issue : #219 is not a duplicate and is actually invalid as it involves a trusted admin to use a function at a wrong time. The assertion that the admin will start a new voting period when one is already running is completely unreasonable. Also, the readme clearly mentions that a keeper bot is meant to start new epochs periodically and its off-chain and out-of-scope. #252 is not a duplicate of this and is invalid/low because it just points out a difference between docs and code but it has no real impact or loss of funds. It talks about the ability to claim rewards later after more epoch periods have passed, which is completely normal and does not relate to a malicious action or a loss to the staker.
There is a separate set of issues described as “expired positions can keep harvesting rewards”. This is not the same as what this issue 166 describes. Fixing 166 by not allowing voting using already expired or to-be-expired-soon during the voting period is not going to fix this set of issues, because harvesting rewards will still be possible in MLUMStaking.sol. This set includes: #6, #530, #362 and #253 This set should be made a separate medium issue. It requires expired locks to be kicked or harvesting to be disabled for already expired locks. |
You've created a valid escalation! To remove the escalation from consideration: Delete your comment. You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final. |
#219, #306, #504, #405, #407 , #419; This group is considered invalid under "Admin Input and responsibility", I agree. #252 low/Invalid , I agree (There is an escalation process in 252, so 252 should be evaluated as low/invalid.) #413 I do not agree.(The verdict is that front-running on IOTA is valid) |
Front running becomes possible when the reward schedule is known in advance. There's no necessity to monitor a pool and send transactions within the same block; this can be accomplished an hour earlier. Although it may not be the most suitable title, the issue remains definitively valid. |
@0xSmartContract what do you mean by that? Additionally regarding #413, tx are randomly ordered on the IOTA evm which makes frontrunning impossible. The IOTA EVM documentation also states this: "To protect against Maximal Extractable Value attacks, the IOTA Smart Contract chain natively randomizes transaction ordering, making it impossible to determine the content of a block in order to manipulate it." |
Front-running on IOTA is valid This issue was discussed and confirmed with Sherlock officials; |
If the head of judging is of that opinion I guess we'll have to accept it. Although it makes almost no sense on a sandwiching attack, as the user would only be able to extract a minor part of the funds as he has to split his capital used for the sandwich into many txs. Nevertheless could you tell me what you meant by the quoted part on top of my message? |
A set was mentioned in Escalate, I just wanted to say that this issue should not be separated into a different set. |
What's your reasoning for that? As mentioned by me on the escalation of #6 these are completely different issues. |
|
I disagree with your take that these are the same issues. Just because they happen to be in the same component of functionality, they can't be duped. One problem exists in the voter contract, and another exists in MLUMStaking. In 166, we need to check for remaining lock duration which can also expire during the period itself. Thus the solution for 6 which is to kick expired positions is not going to solve 166 as positions that have not expired yet but soon-to-expire will still be able to take advantage in voting. They have separate problems and solutions, and are not dups.
Not entirely true. 166 is also about soon-to-expire positions (ie. anytime in the next 14 days) and they can't be kicked.
Again not true due to the involvement of soon-to-expire positions
Now that is completely false. 166 proposes to check remaining duration and not to "revoke positions" as some positions might still be active and would expire during the period itself, they can't be simply kicked. |
This is a similar impact. But this is no reason for grouping issues. If you find 10 different ways to drain funds in a contract with different root causes you also can't merge them into one issue just because they all have the same impact.
This is a similar scenario, but still no reason for duping. That would be the same if you had multiple issues that occur while a contract is paused, but all originate from different root causes. You also can't duplicate those together.
This is not true. #166 does not state anything about revoking the positions once they are expired. It just fixes the if statement. |
Result: |
Escalations have been resolved successfully! Escalation status:
|
The Lead Senior Watson signed off on the fix. |
cocacola
High
Voting does not take into account end of staking lock period
Summary
The protocol allows to vote in
Voter
contract by means of staked position inMlumStaking
. To vote, user must have staking position with certain properties. However, the voting does not implement check against invariant that the remaining lock period needs to be longer then the epoch time to be eligible for voting. Thus, it is possible to vote with stale voting position. Additionally, if position's lock period finishes inside of the voting epoch it is possible to vote, withdraw staked position, stake and vote again in the same epoch. Thus, voting twice with the same stake amount is possible from time to time. Ultimately, the invariant that voting once with same balance is only allowed is broken as well.The voting will decide which pools receive LUM emissions and how much.
Vulnerability Detail
The documentation states that:
User who staked position in the
MlumStaking
contract gets NFT minted as a proof of stake with properties describing this stake. Then, user can use that staking position to vote for pools by means ofvote()
inVoter
contract. Thevote()
functions checks ifinitialLockDuration
is higher than_minimumLockTime
andlockDuration
is higher than_periodDuration
to process further. However, it does not check whether the remaining lock period is longer than the epoch time.Thus, it is possible to vote with stale staking position.
Also, current implementation makes
renewLockPosition
andextendLockPosition
functions useless.The documentation states that minimum lock period for staking to be eligible for voting is 90 days.
The documentation states that voting for pools occurs biweekly.
Thus, assuming the implementation with configuration presented in the documentation, every 90 days it is possible to vote twice within the same voting epoch by:
Proof of Concept
Scenario 1:
Scenario 2:
Impact
A user can vote with stale staking position, then withdraw the staking position with any consequences.
Additionally, a user can periodically vote twice with the same balance of staking tokens for the same pool to increase unfairly the chance of the pool being selected for further processing.
Code Snippet
https://github.com/sherlock-audit/2024-06-magicsea/blob/main/magicsea-staking/src/Voter.sol#L172
https://github.com/sherlock-audit/2024-06-magicsea/blob/main/magicsea-staking/src/Voter.sol#L175
Tool used
Manual Review
Recommendation
It is recommended to enforce the invariant that the remaining lock period must be longer than the epoch time to be eligible for voting.
Additionally, It is recommended to prevent double voting at any time. One of the solution can be to prevent voting within the epoch if staking position was not created before epoch started.
The text was updated successfully, but these errors were encountered: