Platform: Code4rena
Start Date: 03/05/2022
Pot Size: $75,000 USDC
Total HM: 6
Participants: 55
Period: 7 days
Judge: Albert Chon
Total Solo HM: 2
Id: 116
League: COSMOS
Rank: 17/55
Findings: 2
Award: $738.00
🌟 Selected for report: 0
🚀 Solo Findings: 0
When the cumulative power of validators in _newValset
is less than or equal to state_powerThreshold
, the checkValidatorSignatures
function would fail. Eventually, submitBatch
, submitLogicCall
& updateValset
would fail for the new set of validators. This will cause the contract non-functional, as updateValset
can not be updated anymore with any new set of validators to fix it.
Manual review
Add the following validation code fix in updateValset
function.
// Check cumulative power to ensure the contract has sufficient power to actually // pass a vote uint256 cumulativePower = 0; for (uint256 i = 0; i < _newValset.powers.length; i++) { cumulativePower = cumulativePower + _newValset.powers[i]; if (cumulativePower > state_powerThreshold) { break; } } require( cumulativePower > state_powerThreshold, "Submitted validator set signatures do not have enough power." );
#0 - V-Staykov
2022-05-11T11:22:52Z
Duplicate of #123
🌟 Selected for report: IllIllI
Also found by: 0x1337, 0x1f8b, 0xDjango, 0xkatana, AmitN, CertoraInc, Dravee, Funen, GermanKuber, GimelSec, Hawkeye, JC, MaratCerby, WatchPug, Waze, broccolirob, cccz, ch13fd357r0y3r, cryptphi, danb, defsec, delfin454000, dipp, dirk_y, ellahi, gzeon, hake, hubble, ilan, jah, jayjonah8, kebabsec, kirk-baird, m9800, orion, oyc_109, robee, shenwilly, simon135, sorrynotsorry
117.6565 USDC - $117.66
The verifySig function of Gravity.sol calls the Solidity ecrecover function directly to verify the given signatures. However, the ecrecover EVM opcode allows malleable (non-unique) signatures and thus is susceptible to replay attacks.
Although a replay attack seems not possible here since the nonce is increased each time, ensuring the signatures are not malleable is considered a best practice (and so is checking _signer != address(0), where address(0) means an invalid signature).
Contract : Gravity.sol Function : verifySig
Use the recover function from OpenZeppelin's ECDSA library for signature verification.
SafeMath library functions are not always used in the Gravity contract's arithmetic operations, which could cause integer underflow/overflows. Using SafeMath is considered a best practice that could completely prevent underflow/overflows and increase code consistency.
Contract : Gravity.sol Function : checkValidatorSignatures(...) line 244 : cumulativePower = cumulativePower + _currentPowers[i];
Function : constructor(...) line 661 : cumulativePower = cumulativePower + _powers[i];
Consider using the SafeMath library functions in the above mentioned lines of code.
In the constructor additional check for _gravityId not to be null, and _powerThreshold to be greater than 0, can be added.
Contract : Gravity.sol Function : constructor (...)
Add appropriate require statement checking the input parameters mentioned above for the constructor
Add a struct "Signature" which contains the v, r, and s components of a validator signature, This is a more compact encoding and removes the possibility of mismatched signature array lenghts.
Furthermore this reduces our total stack usage and allows us to declare validator sets and signatures to be of type 'calldata' universally.
// This represents a validator signature struct Signature { uint8 v; bytes32 r; bytes32 s; }
Contract : Gravity.sol Functions : testCheckValidatorSignatures, verifySig, checkValidatorSignatures, updateValset, submitBatch, submitLogicCall
Refer to the code fix in https://github.com/Gravity-Bridge/Gravity-Bridge/commit/2bd0837b3ef52fe2f2abc705fc72f371e047c857
Use constants to improve security by preventing assignments and increase performance by explicitly flagging this constant.
Contract : CosmosERC20 in CosmosToken.sol Line 5 : uint256 MAX_UINT = 2**256 - 1;
Change the above line to
uint256 constant MAX_UINT = 2**256 - 1;