Closed sherlock-admin3 closed 4 months ago
1 comment(s) were left on this issue during the judging contest.
WangAudit commented:
seems to be working correctly since it deletes non-eligible proposals; and in the second loop it only accounts only for eligible proposals
We think this issue is correct, at low severity, and is the same as #29
Invalidation reasons:
Therefore, it's a low severity therefore, invalid.
We are working on a fix that will better filter out proposals.
Escalate
This should be at least medium
.
Even though the issue lies within the view
function, its impact
is significant.
Users heavily depend on this function to obtain parameters for the updateRewardsForProposalWritingAndVoting
function, which is known to consume a considerable amount of gas.
Consequently, if the getVotingClientIds
function returns incorrect results, users may incur substantial losses due to massive gas fees.
Additionally, manually identifying the revert reason is challenging, as I highlighted in my issue #29.
Escalate
This should be at least
medium
.Even though the issue lies within the
view
function, itsimpact
is significant. Users heavily depend on this function to obtain parameters for theupdateRewardsForProposalWritingAndVoting
function, which is known to consume a considerable amount of gas. Consequently, if thegetVotingClientIds
function returns incorrect results, users may incur substantial losses due to massive gas fees. Additionally, manually identifying the revert reason is challenging, as I highlighted in my issue #29.
The escalation could not be created because you are not exceeding the escalation threshold.
You can view the required number of additional valid issues/judging contest payouts in your Profile page, in the Sherlock webapp.
As I've said earlier, this is helper function, users can use it, but not obligated to do so. Moreover, as it's said the correct clientId can be manually constructed. Therefore, I believe reasons that it's challenging to construct such array or it's gas intensive functions are not sufficient enough for a medium.
Escalate
I think this should be medium
- getVotingClientIds is a view helper function, therefore, it's not mandatory to use it and users can get the clientId array themselves manually. Hence, it's invalida under Sherlock's rules about return value of view functions.
As comments in Rewards.sol#L491, Returns the clientIds that are needed to be passed as a parameter to updateRewardsForProposalWritingAndVoting, getVotingClientIds
is not just a view function, it's also a helper for updateRewardsForProposalWritingAndVoting
And quoting from sherlock judging rule
16.Incorrect values in View functions are by default considered low.
Exception: In case any of these incorrect values returned by the view functions are used as a part of a larger function which would result in loss of funds then it would be a valid medium/high depending on the impact.
- Even if we use getVotingClientIds and then get a revert, we can extract incorrect clientId of the array, run it again successfully.
Yes, if updateRewardsForProposalWritingAndVoting
get reverted, we can extract incorrect clientId of the array, run it again. But it's not the case for a non-tech user. For a non-tech user, he/she relies on getVotingClientIds's
return value to call updateRewardsForProposalWritingAndVoting
.
Another issue is that: suppose non-tech users calls updateRewardsForProposalWritingAndVoting
at timestamp T1, he/she uses P1 as lastProposalId
, and if success, all related clientId
will gets X1
as rewardPerVote
.
But his call revert, and then sometime later, a tech user will call updateRewardsForProposalWritingAndVoting
again, but this time he might not use the same lastProposalId
as P1, he might use some other value instead. In such case, the rewardPerVote
might not be equal to previous one, so the rewards for one clientId
might be changed because of different parameters.
Just because it can be fixed by tech user, I think it should be medium
. If it can't be fixed by a tech user, I think it should be high
Escalate
I think this should be medium
- getVotingClientIds is a view helper function, therefore, it's not mandatory to use it and users can get the clientId array themselves manually. Hence, it's invalida under Sherlock's rules about return value of view functions.
As comments in Rewards.sol#L491, Returns the clientIds that are needed to be passed as a parameter to updateRewardsForProposalWritingAndVoting,
getVotingClientIds
is not just a view function, it's also a helper forupdateRewardsForProposalWritingAndVoting
And quoting from sherlock judging rule
16.Incorrect values in View functions are by default considered low. Exception: In case any of these incorrect values returned by the view functions are used as a part of a larger function which would result in loss of funds then it would be a valid medium/high depending on the impact.
- Even if we use getVotingClientIds and then get a revert, we can extract incorrect clientId of the array, run it again successfully.
Yes, if
updateRewardsForProposalWritingAndVoting
get reverted, we can extract incorrect clientId of the array, run it again. But it's not the case for a non-tech user. For a non-tech user, he/she relies ongetVotingClientIds's
return value to callupdateRewardsForProposalWritingAndVoting
.Another issue is that: suppose non-tech users calls
updateRewardsForProposalWritingAndVoting
at timestamp T1, he/she uses P1 aslastProposalId
, and if success, all relatedclientId
will getsX1
asrewardPerVote
. But his call revert, and then sometime later, a tech user will callupdateRewardsForProposalWritingAndVoting
again, but this time he might not use the samelastProposalId
as P1, he might use some other value instead. In such case, therewardPerVote
might not be equal to previous one, so the rewards for oneclientId
might be changed because of different parameters.Just because it can be fixed by tech user, I think it should be
medium
. If it can't be fixed by a tech user, I think it should behigh
You've created a valid escalation!
To remove the escalation from consideration: Delete your comment.
You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.
Yes, the rule says, that Exception: In case any of these incorrect values returned by the view functions are used as a part of a larger function which would result in loss of funds then it would be a valid medium/high depending on the impact.
This function is not a part of larger function. It's a helper function. Users are not obligated to use it and they can get the clientId array. I don't think that argument "it's challenging for non-tech users" is not enough for it being a medium.
I believe the rule about view functions correctly invalidates this issue, because it's NOT a part of a large function, it's a helper for that large function, which can be successfully completed without running getVotingClientIds
Despite it is a helper function, it yields incorrect results.
I believe that it is difficult to determine the correct input for the updateRewardsForProposalWritingAndVoting
function, particularly when a significant amount of time has passed since the last update.
As indicated in the comment below for getVotingClientIds
function, most users will depend on this function for accurate input even though it is not mandatory to use.
/**
* @notice Returns the clientIds that are needed to be passed as a parameter to updateRewardsForProposalWritingAndVoting
* @dev This is not meant to be called onchain because it may be very gas intensive.
*/
However, when users call updateRewardsForProposalWritingAndVoting
function with wrong parameters , it results in a revert and consumes a large amount of gas.
I'm new to Sherlock, so I'm not familiar with its rules.
Nevertheless, if all view
functions are considered as low, what purpose does it serve to include them in the scope?
We could just skip view
functions.
I appreciate your kind review
Not all view functions are considered low. There are lots of view functions (in every contest) that is called during the larger non-view function. Therefore, the only view functions that are out of scope are the functions that are used separately and all other functions can be successfully called without this view functions.
This is our case, we can successfully call updateRewardsForProposalWritingAndVoting
without calling getVotingCliendIds
upfront, therefore, under Sherlock's rule, this specific case is considered low.
Not all view functions are considered low. There are lots of view functions (in every contest) that is called during the larger non-view function. Therefore, the only view functions that are out of scope are the functions that are used separately and all other functions can be successfully called without this view functions.
According to your explanation, it'll be Exception: any view functions called by a larger function....
, in such case, I don't think it can be called Exception
, because it's obvious that the entire code flow has flaw.
I am 100%
sure that getVotingCliendIds
function is important view
function.
Even though using this function is not mandatory, almost users will rely on it.
It is impossible to mention all possible scenarios in the rule.
I suggest we could update rules regarding this kind of issues.
Yes, the rule says, that
Exception: In case any of these incorrect values returned by the view functions are used as a part of a larger function which would result in loss of funds then it would be a valid medium/high depending on the impact.
This function is not a part of larger function. It's a helper function.
Quoting from Hierarchy of truth:
Hierarchy of truth: Contest README > Sherlock rules for valid issues > protocol documentation (including code comments) > protocol answers on the contest public Discord channel.
I think your declaration about the function can be classified as protocol answer
, and so the code comments in Rewards.sol#L491-L492 should have more priority than your declaration :-)
Users are not obligated to use it and they can get the clientId array. I don't think that argument "it's challenging for non-tech users" is not enough for it being a medium.
I think we can agree that non-tech will be reverted, and the tech user can call updateRewardsForProposalWritingAndVoting
by filter out the incorrect clientId.
In such case
lastProposalId
for function updateRewardsForProposalWritingAndVoting
to make his favorite clientId more profit.
Suppose there are N...N+9 ten proposals pending for rewards, and proposalN has the issue. For the non-tech users, they can't claim reward. But for tech-user, he can use N+2 , or N+5 to call function updateRewardsForProposalWritingAndVoting
. Because by using different lastProposalId
, there will be different proposals in Rewards.sol#L323-L326, and different proposals will result different auctionRevenue(because different auction has different biding price)
in Rewards.sol#L333, then different auctionRevenue
will cause different t.votingRewardForPeriod
in Rewards.sol#L342, and different t.votingRewardForPeriod
will generate different t.rewardPerVote
in Rewards.sol#L387, and the rewards is calculated as votes * t.rewardPerVote
in Rewards.sol#L427
So by using different lastProposalId
, he can manipulates the rewards after the proposal is closed.Could Denial-of-Service (DOS), griefing, or locking of contracts count as a Medium (or High) issue? DoS has two separate scores on which it can become an issue: The issue causes locking of funds for users for more than a week. The issue impacts the availability of time-sensitive functions (cutoff functions are not considered time-sensitive). If at least one of these are describing the case, the issue can be a Medium. If both apply, the issue can be considered of High severity. Additional constraints related to the issue may decrease its severity accordingly. Griefing for gas (frontrunning a transaction to fail, even if can be done perpetually) is considered a DoS of a single block, hence only if the function is clearly time-sensitive, it can be a Medium severity issue.
I disagree it can be classified as a DOS. At maximum it's a DOS of one block, cause as I've said users can extract incorrect values manually and call the function successfully. Moreover, others as you call "tech" users can call the function and all the "non-tech" will be able to get the rewards.
Moreover, as I've said earlier, I don't think that the argument "it's challenging for non-tech users to call updateRewardsForProposalWritingAndVoting
without calling getVotingClientIds
is vaible for medium.
I don't understand how my argument can be classified as a "protocol answer". My judging is made according to rule 16 regarding view functions and confirmed by the comment inside the code.
It's obvious that determining the correct input parameters of updateRewardsForProposalWritingAndVoting
function will be challenging for both of tech and non-tech users.
There is a convenient getVotingClientIds
function for this purpose.
Do you think tech users will not trust this function in any case and calculate always the input parameters manually?
I believe almost users(nearly 100%) will use this function.
Once it is reverted, the tech users may try to extract incorrect values and won't believe this function anymore.
Do you believe this is acceptable scenario for protocol?
This kind of vulnerability should be prevented.
I don't think that normal users love the protocol which provides an incorrect functionality in the UI and require complex tech operations to execute this functionality manually.
@WangSecurity , I respect your decision regarding the Sherlock rule, however this is an exceptional case in the technical viewpoint and need comments from the head of judge.
Thanks in advance.
I agree that it may be an exceptional case, even tho as of now I still insist on it to remain low, and as I understand, there are no more new comments from either of the side, therefore, we can leave it for the head of judging to decide. Thank you for bringing up this issue, it may actually be more interesting than it seems.
I disagree it can be classified as a DOS. At maximum it's a DOS of one block, cause as I've said users can extract incorrect values manually and call the function successfully. Moreover, others as you call "tech" users can call the function and all the "non-tech" will be able to get the rewards.
I am not saying this issue should be classified as DOS, what I meant is that the side affect for non-tech user is DOS.
Please show me the code or documents that can support your point of view about At maximum it's a DOS of one block
.
For my understanding if the issue is not fixed by tech user, the function will always revert. And there is no guarantees that the tech user will call the function every block.
Moreover, as I've said earlier, I don't think that the argument "it's challenging for non-tech users to call
updateRewardsForProposalWritingAndVoting
without callinggetVotingClientIds
is vaible for medium.
As I said in previous comments, there will be affects from both sides(tech user and non-tech user). For tech user, he can chose different lastProposalId
to make more profit than expected, if a user can manipulate the parameter to make more profile, I think it's a valid issue.
I don't understand how my argument can be classified as a "protocol answer". My judging is made according to rule 16 regarding view functions and confirmed by the comment inside the code.
It's obvious that we have different understanding about rule 16, that's OK. The issue is that if getVotingClientIds
can't return correct result, the protocol will create a reward mechanism that looks fair, but it's not. For all clientIds, they think they can get rewards fairly, but in fact, tech user can manipulate the rewards.
This issue is a maximum DOS of one block cause if the user calls it with incorrect parameters, then they can extract incorrect clientIds and run the function successfully.
My main argument is mainly that the protocol can function as it should be without getVotingClientIds
function ever called. I know it's hard to get the correct clientId. And the argument that web3 users are not technical enough to make an actually correct clientId array is not a viable argument for this issue to be valid medium.
I see you mention that users can get profit in edge case manipulating lastProposalId
, but it's nowhere mentioned in this report, there is a different escalation on issue #15 regarding it. But it's irrelevant for this report, since I don't see how it mentions getting profit from manipulating lastProposalId
.
These are my arguments and they have not changed since the start of the escalation. At this point we just argue back and forth saying the same words.
If there are no new arguments from your side, we can leave the decision to the head of judging.
I think I'll the the issue to the judge now. @WangSecurity thanks for your time :-D
The issue is fixed in PR-839 as now the filtration logic is moved to proposalDataForRewards()
and the calls to it are the same in both functions.
The protocol team fixed this issue in the following PRs/commits: https://github.com/nounsDAO/nouns-monorepo/pull/839
The Lead Senior Watson signed off on the fix.
Yes, the rule says, that
Exception: In case any of these incorrect values returned by the view functions are used as a part of a larger function which would result in loss of funds then it would be a valid medium/high depending on the impact.
This function is not a part of larger function. It's a helper function. Users are not obligated to use it and they can get the clientId array. I don't think that argument "it's challenging for non-tech users" is not enough for it being a medium.
I believe the rule about view functions correctly invalidates this issue, because it's NOT a part of a large function, it's a helper for that large function, which can be successfully completed without running
getVotingClientIds
I think this comment from the Lead Judge best describes why this problem is Low severity.
By default, every view
function is Low severity. It should be called from another function and there should be a vulnerability because of it and then it can be Medium/High. You can check the Sherlock documentation.
I'm planning to reject the escalation and leave the issue as it is.
Result: Invalid Has Duplicates
jasonxiale
medium
Rewards.getVotingClientIds
doesn't consistent withRewards.updateRewardsForProposalWritingAndVoting
Summary
Rewards.getVotingClientIds
is used to return the clientIds that are needed to be passed as a parameter toRewards.updateRewardsForProposalWritingAndVoting
, without this helper function, it will be impossible for non-tech user to get the correct clientIds, In current implementation, there is a special case the function doesn't return the correct clientIds, which will causesRewards.updateRewardsForProposalWritingAndVoting
revertVulnerability Detail
In Rewards.getVotingClientIds, the function fetch all the clientIds from
$.nextProposalIdToReward
tolastProposalId
in Rewards.sol#L502-L506 And then filter all the clientIds those have been used in Rewards.sol#L508-L519The issue is that when those clientIds passed into Rewards.updateRewardsForProposalWritingAndVoting, the function will delete some proposal in Rewards.sol#L358-L361.
If a
clientIdX
is used only once for a proposalX(and theclientIdX
is not used for the rest proposals), and the proposalX is deleted in Rewards.sol#L358-L361 because ofproposals[i].forVotes < (proposals[i].totalSupply * proposalEligibilityQuorumBps_
, in such case, the function will revert in Rewards.sol#L438-L438 becausedidClientIdHaveVotes[clientIdX]
is 0Impact
In current implementation, there is a special case the function doesn't return the correct clientIds, which will causes
Rewards.updateRewardsForProposalWritingAndVoting
revertCode Snippet
https://github.com/sherlock-audit/2024-03-nouns-dao-2/blob/8f6879efaf831eb7fc9d4a4ad2b62b5334220d87/nouns-monorepo/packages/nouns-contracts/contracts/client-incentives/Rewards.sol#L494-L526
Tool used
Manual Review
Recommendation