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: 35/55
Findings: 2
Award: $180.85
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 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
114.279 USDC - $114.28
ecrecover
allows signature malleability
Auditor shw has previously stated the exact same issue in past audit.
I will simply reuse his report as I don't believe I could offer a clearer explanation.
gravitybridge-findings/issues/61
"The verifySig
function of Gravity
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)."
SWC-117: Signature Malleability SWC-121: Missing Protection against Signature Replay Attacks
Use the recover function from OpenZeppelin's ECDSA library for signature verification.
🌟 Selected for report: GermanKuber
Also found by: 0v3rf10w, 0x1f8b, 0xDjango, 0xNazgul, 0xf15ers, 0xkatana, AlleyCat, CertoraInc, Dravee, Funen, GimelSec, IllIllI, JC, MaratCerby, WatchPug, Waze, defsec, delfin454000, ellahi, gzeon, hake, hansfriese, ilan, jonatascm, nahnah, oyc_109, peritoflores, rfa, robee, simon135, slywaters, sorrynotsorry
66.5732 USDC - $66.57
for
loop optimizationfor (uint256 i = 0; i < _users.length; i++) { require( _users[i] != address(0), "User is the zero address" ); whitelisted[_users[i]] = _isWhitelisted;
Gas could be saved by:
Example:
uint size = _users.length; for (uint256 i = 0; i < size;) { require( _users[i] != address(0), "User is the zero address" ); whitelisted[_users[i]] = _isWhitelisted; unchecked { ++i; } }
Other instances: Gravity.sol#L233 Gravity.sol#L263 Gravity.sol#L453 Gravity.sol#L660