Closed c4-bot-10 closed 7 months ago
Picodes marked the issue as primary issue
othernet-global (sponsor) disputed
The user cannot double vote. If a user stakes, votes, unstakes for two weeks, votes again then they only achieve an additional 20% of their original vote amount - but at an 80% penalty in terms of their owned SALT.
Picodes changed the severity to 2 (Med Risk)
Picodes marked the issue as duplicate of #746
Picodes marked the issue as satisfactory
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/staking/Staking.sol#L60-L79 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/staking/Staking.sol#L101-L126
Vulnerability details
Summary
When a user unstakes
xSALT
any votes they have cast on open ballots are not removed meaninf they can vote on the same ballot with their recoveredSALT
by staking again.Vulnerability Details
In
Staking::unstake()
there is no logic to remove user's vites which they have cast on open ballots. This means that when theyrecoverSALT()
they can simply transfer to another address which has access and the other user can vote on the same ballot.This could be manipulaed in a number of different ways but the protocol's unstaking configuration would need to be taken into account by an attacker. An attacker needs to be willing to take a loss in returned SALT in order to get a vote over the line which earned them a large advantage. In it's default configuration the minimum unstaking term is 2 weeks, which will return
minUnstakePercent
of 20% of a user'sxSALT
inSALT
. To use the exploit an attacker would need to recover theirSALT
before the end of the vote. A vote to send SALT to themselves could net the user enough SALT to cover the losses they incur by unstaking early.The exploit likelihood increases as
minUnstakePercent
is increased towards it's 50% limit andminUnstakeWeeks()
is reduced.There could also arise a situation where quorum is not reached on an early ballot, which the sits open, forgotten about. A user could unstake over the normal time period and use 100% of their voting power to vote again on the ballot and get it across the line.
POC
Add the test function below to
DAO.t.sol
and run:Impact
Very high impact depending on which type of vote a user manipulates and their voting power. User could whitelist a malicious token, send themselves
SALT
from the protocol or update the website url to a malicious address.Tools Used
Manual Review Foundry Testing
Recommendations
Add logic to remove user's current votes from open ballots when they unstake their
xSALT
. Likely requires a new/updated state variable to track what ballots each address has voted on inProposals::castVote()
which can be looped through and vote removed inStaking::unstake()
.Assessed type
Governance