The session result can be manipulated by preventing quorum attainment through multiple calls to submitBlockSpecimenProof
Summary
In the BlockSpecimenProofChain contract, the submitBlockSpecimenProof function allows_blockSpecimenProducers role to submit block specimen proofs. Under the constraint that, for the same blockhash, a producer can only submit one specimenHash, the total submissions for the same producer across different blockHash are limited by maxSubmissionsPerBlockHeigh. However, in the finalizeSpecimenSession function, excessive submissions to different block hashes by a malicious producer for a session could increase the contributorsN value in the condition (max * _DIVIDER) / contributorsN > _blockSpecimenQuorum. This can ultimately prevent the invocation of the _finalizeWithParticipants function due to the failure to meet the quorum condition, resulting in agreed blockHash and specimenHash not being finalized. The root cause of this issue is that the contributorsN calculated in the finalizeSpecimenSession function counts the total number of submissions in a session rather than the total number of participants.
Vulnerability Detail
Assuming _minSubmissionsRequired == 2, maxSubmissionsPerBlockHeight == 3, if producer A calls submitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_1, specimenHash_1, storageURL_1), producer B calls submitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_1, specimenHash_1, storageURL_2), and producer C calls submitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_1, specimenHash_2, storageURL_3), and the session ends at this point, the final agreed blockHash should be blockHash_1, and the agreed specimenHash should be specimenHash_1.
If, before the session ends, producer C maliciously calls submitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_2, specimenHash_3, storageURL_4) and submitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_3, specimenHash_4, storageURL_5), then, due to the constraint (max * _DIVIDER) / contributorsN > _blockSpecimenQuorum, the final agreed blockHash and specimenHash cannot be finalized.
Impact
if a malicious producer continuously submits block specimen proofs with different block hashes before the session has ended, it could prevent the determination of the final agreed blockHash and specimenHash.
zach223
high
The session result can be manipulated by preventing quorum attainment through multiple calls to
submitBlockSpecimenProof
Summary
In the
BlockSpecimenProofChain
contract, thesubmitBlockSpecimenProof
function allows_blockSpecimenProducers
role to submit block specimen proofs. Under the constraint that, for the sameblockhash
, a producer can only submit onespecimenHash
, the total submissions for the same producer across differentblockHash
are limited bymaxSubmissionsPerBlockHeigh
. However, in thefinalizeSpecimenSession
function, excessive submissions to different block hashes by a malicious producer for a session could increase thecontributorsN
value in the condition(max * _DIVIDER) / contributorsN > _blockSpecimenQuorum
. This can ultimately prevent the invocation of the_finalizeWithParticipants
function due to the failure to meet the quorum condition, resulting in agreedblockHash
andspecimenHash
not being finalized. The root cause of this issue is that thecontributorsN
calculated in thefinalizeSpecimenSession
function counts the total number of submissions in a session rather than the total number of participants.Vulnerability Detail
_minSubmissionsRequired == 2
,maxSubmissionsPerBlockHeight == 3
, if producer A callssubmitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_1, specimenHash_1, storageURL_1)
, producer Bcalls submitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_1, specimenHash_1, storageURL_2)
, and producer C callssubmitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_1, specimenHash_2, storageURL_3)
, and the session ends at this point, the final agreedblockHash
should beblockHash_1
, and the agreedspecimenHash
should bespecimenHash_1
.submitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_2, specimenHash_3, storageURL_4)
andsubmitBlockSpecimenProof(chainId_1, blockHeight_1, blockHash_3, specimenHash_4, storageURL_5)
, then, due to the constraint(max * _DIVIDER) / contributorsN > _blockSpecimenQuorum
, the final agreedblockHash
andspecimenHash
cannot be finalized.Impact
if a malicious producer continuously submits block specimen proofs with different block hashes before the session has ended, it could prevent the determination of the final agreed
blockHash
andspecimenHash
.Code Snippet
https://github.com/sherlock-audit/2023-11-covalent/blob/main/cqt-staking/contracts/BlockSpecimenProofChain.sol#L328-L439
Tool used
Manual Review
Recommendation
It is recommended using the following line of code to calculate
contributorsN
:Duplicate of #16