Closed c4-bot-4 closed 5 months ago
Picodes marked the issue as primary issue
othernet-global (sponsor) disputed
Generating whitelisted addresses to vote in the BoootstrapBallot is not possible. The addresses are whitelisted offchain and cannot be added arbitrarily.
Picodes changed the severity to QA (Quality Assurance)
Downgrading to Low for the following reasons:
Picodes marked the issue as grade-c
Lines of code
Vulnerability details
Description
At the launch of the Salty protocol, there would be a BootstrapBallot which initiates the exchange. This ballot allows users with authorized wallets to vote for the exchange launch via the
BootstrapBallot.vote
function.This function checks the user is authorized to vote by verifying their signature using an offchain verifier in
SigningTools._verifySignature
. The function tracks a vote tally viaBoostrapBallot.startExchangeYes
andBootstrapBallot.startExchangeNo
and increments either of these depending on whether the user votes for or against the ballot. At the end of the ballot period an external functionBootstrapBallot.finalizeBallot
is called. This function is extremely important as it initializes the protocol through theInitialDistribution
contract and setspools.startExchangeApproved
to true. In order for this to be possible, the number of for votes must be higher than the number of against votes. Additionally, this ballot does not have a minimum or maximum limit on how many votes are required for this ballot to be considered valid.A malicious user with sufficient motivation and resources may generate multiple (as many as possible) addresses, ensure they are whitelisted and authorized to vote, and then these addresses can sybil the ballot at launch to prevent the exchange from ever going live. This user can achieve this by either ensuring both votes tallies are exactly equal or
startExchangeNo
votes are higher thanstartExchangeYes
votes at the end of the validity period. Alternatively, the user can themselves make the tallies unfavourable for the protocol and then call theBootstrapBallot.finalizeBallot
once the completionTimestamp is reached. If this function is ever called with unfavourable vote tallies, the exchange would never go live as the ballot would get finalized anyway.Impact
The most important functions of this protocol relies
initialDistribution.distributionApproved
andpools().startExchangeApproved
being set when the ballot passes. This would affect staking and adding of liquidity. Essentially, the protocol would be non-functional. Mitigation would require the protocol to be be relaunched.Proof of Concept
Frank wants to prevent the exchange from going live at launch. This maybe a competitor or a malicious user. He discovers there is going to be an initial ballot at launch required to start the exchange.
He prepares numerous fake accounts, as many as possible, and ensures they pass the off chain identity process and are authorized to vote.
At launch, Frank uses each of his authorized wallets to vote against the ballot, ensuring the votes are unfavourable and calls the
BootstrapBallot.finalizeBallot
once the completion time is reached.This causes significant griefing to the owners as once this ballot does not pass, the protocol would essentially be non-functional.
In order to resolve this, a second launch would be required which can be sybilled as many times as possible unless major protocol changes are made.
This may be an expensive attack especially involving passing the offchain identity system but it is still possible.
Tools Used
Manual Review
Recommended Mitigation Steps
Assessed type
DoS