Salty.IO - piyushshukla's results

An Ethereum-based DEX with zero swap fees, yield-generating Automatic Arbitrage, and a native WBTC/WETH backed stablecoin.

General Information

Platform: Code4rena

Start Date: 16/01/2024

Pot Size: $80,000 USDC

Total HM: 37

Participants: 178

Period: 14 days

Judge: Picodes

Total Solo HM: 4

Id: 320

League: ETH

Salty.IO

Findings Distribution

Researcher Performance

Rank: 127/178

Findings: 1

Award: $31.20

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
duplicate-844

Awards

31.1969 USDC - $31.20

External Links

Lines of code

https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L259

Vulnerability details

Impact

The voting system, particularly the castVote function, is susceptible to exploitation by malicious users. This vulnerability enables them to manipulate votes and approve malicious contracts, leading to the drainage of funds from the system.

Proof of Concept

  • A malicious user holds a substantial number of tokens within the system.
  • The user transfers tokens to multiple addresses controlled by them to amplify their voting power.
  • Using the castVote function, the malicious user casts votes across multiple addresses to influence voting outcomes.
  • They strategically distribute votes to approve malicious contracts that drain funds from the system.
  • Through the manipulation of votes, malicious contracts proposed by the attacker are approved by the governance system.

https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L259C1-L293C4

function castVote( uint256 ballotID, Vote vote ) external nonReentrant { Ballot memory ballot = ballots[ballotID]; // Require that the ballot is actually live require( ballot.ballotIsLive, "The specified ballot is not open for voting" ); // Make sure that the vote type is valid for the given ballot if ( ballot.ballotType == BallotType.PARAMETER ) require( (vote == Vote.INCREASE) || (vote == Vote.DECREASE) || (vote == Vote.NO_CHANGE), "Invalid VoteType for Parameter Ballot" ); else // If a Ballot is not a Parameter Ballot, it is an Approval ballot require( (vote == Vote.YES) || (vote == Vote.NO), "Invalid VoteType for Approval Ballot" ); // Make sure that the user has voting power before proceeding. // Voting power is equal to their userShare of STAKED_SALT. // If the user changes their stake after voting they will have to recast their vote. uint256 userVotingPower = staking.userShareForPool( msg.sender, PoolUtils.STAKED_SALT ); require( userVotingPower > 0, "Staked SALT required to vote" ); // Remove any previous votes made by the user on the ballot UserVote memory lastVote = _lastUserVoteForBallot[ballotID][msg.sender]; // Undo the last vote? if ( lastVote.votingPower > 0 ) _votesCastForBallot[ballotID][lastVote.vote] -= lastVote.votingPower; // Update the votes cast for the ballot with the user's current voting power _votesCastForBallot[ballotID][vote] += userVotingPower; // Remember how the user voted in case they change their vote later _lastUserVoteForBallot[ballotID][msg.sender] = UserVote( vote, userVotingPower ); emit VoteCast(msg.sender, ballotID, vote, userVotingPower); }

Tools Used

Address Whitelisting:

Implement address whitelisting to restrict voting rights to verified addresses.

Assessed type

Governance

#0 - c4-judge

2024-02-02T11:15:11Z

Picodes marked the issue as duplicate of #746

#1 - c4-judge

2024-02-14T08:05:59Z

Picodes marked the issue as satisfactory

#2 - c4-judge

2024-02-17T16:35:42Z

Picodes changed the severity to 2 (Med Risk)

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter