Closed c4-bot-2 closed 8 months ago
Picodes marked the issue as duplicate of #620
Picodes changed the severity to 2 (Med Risk)
Picodes changed the severity to QA (Quality Assurance)
This previously downgraded issue has been upgraded by Picodes
Picodes marked the issue as satisfactory
Lines of code
https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L102-L103 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L240-L246 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/Proposals.sol#L249-L255 https://github.com/code-423n4/2024-01-salty/blob/53516c2cdfdfacb662cdea6417c52f23c94d5b5b/src/dao/DAO.sol#L203-L208
Vulnerability details
Impact
According to documentation, ballots created with
proposeSetContractAddress
andproposeWebsiteUpdate
functions are considered higher impact proposals. When these proposals are finalized, a new ballot is created withcreateConfirmationProposal
and is voted on again.A DAO member can propose a new contract address by calling the
Proposals::proposeSetContractAddress()
function with specifying contractName, newAddress and description parameters. With this contractName, a ballot is created. For example, if the DAO member wants to propose a change topriceFeed1
, the contractName parameter they need to provide to the function ispriceFeed1
, and the resultingballotName
will be "setContract:priceFeed1". This ballot can be finalized when it receives enough votes to reach a quorum and afterballotMinimumEndTime
has passed. When this ballot is finalized, theProposals::createConfirmationProposal()
function is called. This function takes theballotName
and appends "_confirm" to the end of it. Thus, theballotName
becomes "setContract:priceFeed1_confirm". TheProposals
contract registers eachballotName
in theopenBallotsByName
mapping to prevent the creation of multiple ballots with the same name. If a malicious user calls theProposals::proposeSetContractAddress()
function before the ballot's finalization tx and sets the contractName to "priceFeed1_confirm" (Maybe even by constantly scanning the mempool via a bot and creating proposals with a contractName ending with "_confirm" for every proposed ballotName before finalizing), then the resultingballotName
will be "setContract:priceFeed1_confirm". In this case theballotName
that is being attempted to finalize withProposals::createConfirmationProposal()
cannot be registered in theopenBallotsByName
mapping again, and the transaction will revert.Since this same attack vector also applies to
proposeWebsiteUpdate
, it will prevent the both most important ballots of changing the contract address and changing the website URL from being finalized.Proof of Concept
For the test to work properly, add this to the
DAO.t.sol
constructor;The following tests demonstrates user causing a denial of service with
Proposals::proposeSetContractAddress
andProposals::proposeWebsiteUpdate
functions. You can add it toDAO.t.sol
.Tools Used
Manual Review and Foundry
Recommended Mitigation Steps
You can add a string checking logic as follows and enforce with require in other functions.
Assessed type
DoS