Closed c4-bot-2 closed 4 months ago
Picodes marked the issue as primary issue
othernet-global (sponsor) disputed
This is acceptable as the attacker would have to stake a significant amount of SALT to affect quorum - and then would not be able to unstake it immediately due to the unstaking mechanism.
Downgrading to Low as although the mechanism is not standard the sponsor's reasoning is convincing.
Picodes changed the severity to QA (Quality Assurance)
Based on your responses, this means we are both on the same page about the quorum being easily manipulated, I will now make some points to address your response
Let's consider a situation about what I am talking about, A Situation where the DAO barely meets the required quorum
BEFORE ATTACK Total Amount Of SALT staked = 5,000,000 Default 10% required Quorum base = 500,000 Quorum for Whitelisting - 2 * baseQuorum = 1,000,000
The DAO Meets the required quorum by 1,000,005, Which is by 5
AFTER ATTACK
Attacker stakes SALT = 100
Total Amount Of SALT staked = 5,000,100 Default 10% required Quorum base = 500,010 Quorum for Whitelisting - 2 * baseQuorum = 1,000,020
The difference of How much the attacker made the quorum short Whitelisting - 20 SALT
The 100 SALT is enough to manipulate the ballot and prevent the 1,000,005 SALT Achieved by the DAO from being unable to meet the newly manipulated Quorum
The example I gave in this report is not about the required amount to successfully carry out the attack, but to ensure that the deficit in the manipulated quorum is enough, to make sure the DAO does not reach that quorum like a situation where the DAO beats the required quorum by a decent amount, then more SALT are needed to perform the attack, an attacker may as well sit and track every vote being cast on-chain and calculate the quorum and then the amount of SALT, they would need to Acquire and STAKE to manipulate the required Quorum and DOS The Ballots
The only trusted role is the DAO. There is no other ownership or privileged role as the exchange is decentralized at launch.
Another point is about how other DAOs in most protocols operate and how I believe the finalizing should be done, Most DAOs do not Calculate The Quorum directly with the current amount of voting tokens available, as this is susceptible to a large amount of voting tokens being acquired, through flash loans or other means i. At the moment the ballot is opened for voting, a snapshot of the current amount of staked salt should be taken, this way manipulation is not possible in any form, hereby using the current amount of SALT when the ballot was created and calculating the quorum from that prevents the manipulation of the finalization ii. Most protocols utilize this system, to prevent the same manipulation we are talking about, a situation where a malicious user acquires a huge amount of Voting tokens to manipulate the result of the proposal
Viewing this attack as the attacker will lose tokens but this is not entirely accurate as The protocol just Locks the attacker's SALT for a Year, to a malicious attacker, which is an acceptable trade-off to perform an attack on critical ballots that will hurt the protocol.
Final Points, In the contest page the Attack Ideas section included issues that will affect the DAO
Any issue that would prevent the DAO from functioning correctly.
@Hopizi thank you for your comment. I still believe what you are describing in your report is an acceptable consequence of the design chosen by the sponsor.
Ballots can't be finalized if the quorum isn't reached and people could still vote. So if someone stakes to increase the quorum, someone else can just vote to match the quorum increase. It only delays the execution of the proposal - which is fine because if the proposal is urgent we assume it will be way above the quorum and this won't be possible - and the upside for the protocol is that more people staked.
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L385-L400 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L317-L339 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/DAO.sol#L278-L291
Vulnerability details
Impact
The vulnerability presents itself in a way that it is possible for a user to stop important ballots from passing for a period. This is possible because the finalizeBallot function when finalizing ballots, uses the current staked SALT to get the required quorum as a requirement, but does not take into account that between that time it takes for someone to call
finalizeBallot
the previous amount of Staked SALT that allowed them to reach quorum might have changed, by someone staking a substantial amount of SALT therefore increasing the required quorum they thought they had reached, hence making the proposal unpassable. That lack of check is what exactly will allow the malicious user to acquire and stake a substantial amount of SALT and brick Ballots especially if the Ballot are important and urgent Changes for the Protocol.Proof of Concept
A Detailed Narrative of a Concept of how this attack can take place is as Follows
3 Ballots are proposed
Whitelisting Ballots - 1 Approval Ballots - 2
These Requires 2 baseBallotQuorum and 3 baseBallotQuorum respectively
Before the finalize Ballot is called, the attacker stakes a substantial amount of SALT to change the quorum from what the DAO members thought it was to a even higher figure.
To show you the difference we will create a scenario to show the difference before and after the attack
BEFORE ATTACK
Total Amount Of SALT staked = 5,000,0000 Default 10% required Quorum base = 500,000 Quorum for Whitelisting - 2 baseQuorum = 1,000,000 Quorum for Approvals - 3 baseQuorum = 1,500,000
AFTER ATTACK
Attacker stakes SALT = 1,500,000
Total Amount Of SALT staked = 6,500,0000 Default 10% required Quorum base = 650,000 Quorum for Whitelisting - 2 baseQuorum = 1,300,000 Quorum for Approvals - 3 baseQuorum = 1,950,000
Difference of How much the attacker made the quorum short
Whitelisting - 300,000 SALT Approvals - 450,000 SALT
finalizeBallot
is called the following happens, and they are unable to finalizehttps://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/DAO.sol#L278C2-L291C4
DAO::finalizeBallot
, when called callsProposals::canFinalizeBallot
to check if the Ballot can actually be finalized as shown belowhttps://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L385C2-L400C7
The First two checks will pass but on a closer look at the third check we can see where the vulnerability that allows the attacker to exploit as shown below
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L317C2-L339C4
uint256 totalStaked = staking.totalShares( PoolUtils.STAKED_SALT );
to get totalStaked including the attackers newly staked SALTWhich Means All the ballot that called finalizeBallot After the attackers action will be unable to finalize and get their proposals passed
NOTE: the mathematical example used is just for demonstration purposes, the level of the attack can be much larger than that, it can go as far as the attacker is willing to go.
Tools Used
Manual Review
Recommended Mitigation Steps
A New Staking meant for system should be considered, because it is somehow easy for a determined attacker to brick ballots at will, it all depends on how much of SALT they are willing to stake to achieve their Goal.
Assessed type
DoS