Platform: Code4rena
Start Date: 09/11/2021
Pot Size: $30,000 ETH
Total HM: 6
Participants: 17
Period: 3 days
Judge: pauliax
Total Solo HM: 3
Id: 50
League: ETH
Rank: 7/17
Findings: 2
Award: $734.40
π Selected for report: 1
π Solo Findings: 0
0.007 ETH - $33.11
gzeon
Unnecessary require statement in setMembershipWallets
L527 as the length of the array must be 3
#0 - YunChe404
2021-11-14T17:16:33Z
Max 3 wallets exist currently for one membership. They are: that of the msg.sender
plus the additional two in case they are needed, leading to an invalid exhibit.
#1 - pauliax
2021-11-16T23:41:35Z
Based on my interpretation, the warden wanted to say that the "require" statement for wallets length is not really necessary as the array cannot exceed 2 elements (I think the warden mistakenly wrote 3).
#2 - pauliax
2021-11-17T10:41:45Z
Marking this as a duplicate of #56
0.0172 ETH - $81.35
gzeon
Per docstring in L595
It is the minimum between 100 ETH and 0.05% of the capital pool. However we have this is L601
return minimumMaxBenefit > dynamicMaxBenefit ? minimumMaxBenefit : dynamicMaxBenefit;
which return the maximum of the 2 variable instead
Depending on the expected behavior. Do note that if the behavior is not intended (i.e. docstring is correct), L245 will fail when there is no deposit in the contract and you cannot deposit because it revert.
#0 - YunChe404
2021-11-14T14:24:04Z
Comments do not pose any actual threat, so severity should be lowered to level zero.
#1 - pauliax
2021-11-17T15:04:03Z
A duplicate of #41.
π Selected for report: gzeon
0.131 ETH - $619.94
gzeon
While assessors is a privileged role, it is sort of a 2-of-n multisig. However, there is a possible DOS by 1 of the assessor in some situation. 1 of the assessor can replay the signature of Action.SubmitEvidence or Action.ExtendClaim signed by 1 of the 2 other assessor. It would allow him to reset csr.votingOpen indefinitely. While no voting mechanism is currently implemented, this certainly opened up a possibility of deadlock if not dealt with.
#0 - YunChe404
2021-11-14T17:19:00Z
Each action will change the signature, as the action is an input of the signature creation.
#1 - pauliax
2021-11-19T11:31:14Z
I think the warden wanted to say that the same signature can be used again to trigger this branch and repeatedly set csr.votingOpen or csr.evidence:
} else if ( action == Action.SubmitEvidence || action == Action.ExtendClaim ) { require( _isApprovedByAssessors(sig, id, action), "FSDNetwork::updateCostShareRequest: Insufficient Privileges" ); CostShareRequest storage csr = costShareRequests[id]; csr.votingOpen = uint128(block.timestamp); if (action == Action.SubmitEvidence) { // Should represent hash of evidence csr.evidence = abi.decode(data, (bytes32)); } }
While the action is part of the signature, here it will be the same action, so the signature will not change. Usually, it is a good practice to increment nonces, so the same signature cannot be replicated.
I will leave this issue as of Medium severity, although the current impact cannot be estimated as the warden mentioned it lacks the implementation and no usage of 'votingOpen' or 'evidence' is present in the codebase.
#2 - pauliax
2021-11-19T11:35:01Z
Also, by looking at this updateCostShareRequest function I have noticed something from myself:
* Requirements: * - only callable by governance or timelock contracts.
However, this function contains no auth checks I expected to see:
require( msg.sender == GOVERNANCE_ADDRESS || msg.sender == TIMELOCK, "FSDNetwork::setSlippageTolerance: Insufficient Privileges" );
Anyone can call it supposed they have a valid signature. Because evidence data is not part of the signature, anyone can pass any arbitrary value. Make sure that's the intended behavior.
#3 - YunChe404
2021-11-19T17:50:32Z
Thank you for looking into it. The comment is leftover from the original implementation. With regards to the finding, assessors can be voted on and off by the DAO. As a result, this is a non-critical finding.
#4 - pauliax
2021-11-19T19:25:46Z
Despite voting off the malicious accessor, I think the issue remains. The function does not have any auth check thus a signature for the aforementioned actions can be replicated by anyone else, not only accessor.
#5 - YunChe404
2021-11-19T20:32:22Z
If you inspect the _isApprovedByAssessors
function, you will see that the caller is mandated to be an assessor. As such, it cannot be replicated by anyone else. Additionally, the issue only manifests when the malicious assessor is the one that did not sign the payload. In general, its a privileged only function and voting off assessors is a protocol feature. Otherwise, malicious assessors could harm the system to a great degree
#6 - pauliax
2021-11-20T11:31:22Z
You are right, this function is only accessible by assessors. However, the issue is still present, even not that significant, so I am lowering the severity to 'Low'.