Platform: Code4rena
Start Date: 07/08/2023
Pot Size: $36,500 USDC
Total HM: 11
Participants: 125
Period: 3 days
Judge: alcueca
Total Solo HM: 4
Id: 274
League: ETH
Rank: 115/125
Findings: 1
Award: $4.23
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: RED-LOTUS-REACH
Also found by: 0x3b, 0x4non, 0xCiphky, 0xDING99YA, 0xDetermination, 0xE1, 0xG0P1, 0xStalin, 0xWaitress, 0xbrett8571, 0xhacksmithh, 0xkazim, 0xmuxyz, 0xweb3boy, 14si2o_Flint, AlexCzm, Alhakista, Bube, Bughunter101, Deekshith99, Eeyore, Giorgio, HChang26, InAllHonesty, JP_Courses, KmanOfficial, MatricksDeCoder, Mike_Bello90, MrPotatoMagic, Naubit, QiuhaoLi, RHaO-sec, Raihan, Rolezn, SUPERMAN_I4G, Shubham, Silverskrrrt, Strausses, T1MOH, Topmark, Tripathi, Watermelon, _eperezok, aakansha, auditsea, audityourcontracts, ayden, carlos__alegre, castle_chain, cducrest, ch0bu, d23e, deadrxsezzz, deth, devival, erebus, fatherOfBlocks, halden, hassan-truscova, hpsb, hunter_w3b, imkapadia, immeas, jat, kaden, kaveyjoe, klau5, koxuan, kutugu, ladboy233, lanrebayode77, leasowillow, lsaudit, markus_ether, matrix_0wl, merlin, nemveer, ni8mare, nonseodion, oakcobalt, owadez, p_crypt0, pipidu83, piyushshukla, popular00, ppetrov, rjs, sandy, sl1, supervrijdag, tay054, thekmj, wahedtalash77, windhustler, zhaojie
4.2289 USDC - $4.23
https://github.com/code-423n4/2023-08-verwa/blob/6686cf4fef5ec15582ccd9a62232e8c1253e8fc0/src/GaugeController.sol#L58-L59 https://github.com/code-423n4/2023-08-verwa/blob/6686cf4fef5ec15582ccd9a62232e8c1253e8fc0/src/GaugeController.sol#L118-L122
Risk:
Recommendation:
constructor(address _votingEscrow, address _governance) { require(_votingEscrow != address(0)); require(_governance != address(0)); votingEscrow = VotingEscrow(_votingEscrow); governance = _governance; // TODO: Maybe change to Oracle uint256 last_epoch = (block.timestamp / WEEK) * WEEK; time_sum = last_epoch; } function add_gauge(address _gauge) external onlyGovernance { require(_gauge != address(0)); require(!isValidGauge[_gauge], "Gauge already exists"); isValidGauge[_gauge] = true; emit NewGauge(_gauge); }
https://github.com/code-423n4/2023-08-verwa/blob/6686cf4fef5ec15582ccd9a62232e8c1253e8fc0/src/GaugeController.sol#L188-L199 https://github.com/code-423n4/2023-08-verwa/blob/6686cf4fef5ec15582ccd9a62232e8c1253e8fc0/src/GaugeController.sol#L204-L206
Risks:
Recommendation:
function _change_gauge_weight(address _gauge, uint256 _weight) internal { require(_gauge != address(0)); require(_weight != 0);
OR
function change_gauge_weight(address _gauge, uint256 _weight) public onlyGovernance { require(_gauge != address(0)); require(_weight != 0); _change_gauge_weight(_gauge, _weight); }
2. No explicit user access control implemented for function vote_for_gauge_weights():
The usage of timestamps and the calculation of time intervals might introduce vulnerabilities due to miners' potential manipulation of timestamps. Be cautious and consider using block numbers or other mechanisms for timing.
The change_gauge_weight() function should use the external
visibility modifier instead of public
, as it directly calls the internal version, and doesn't seem to be called internally itself.
Even though gas optimization is not in scope for this contest, using the external
modifier instead is recommended as best practice.
https://github.com/code-423n4/2023-08-verwa/blob/6686cf4fef5ec15582ccd9a62232e8c1253e8fc0/src/VotingEscrow.sol#L26-L27 https://github.com/code-423n4/2023-08-verwa/blob/6686cf4fef5ec15582ccd9a62232e8c1253e8fc0/src/VotingEscrow.sol#L36
Recommendation:
Instead of doing:
struct LockedBalance { int128 amount; uint256 end; int128 delegated; address delegatee; }
Do this:
struct LockedBalance { uint256 end; int128 amount; int128 delegated; address delegatee; }
7. Any reason why these two if
statements weren't combined into one if
statement block? I could not see any legit reason other than the intention to keep them separate for readability/"modularity" ?
if (_addr != address(0)) { // If last point was in this block, the slope change has been applied already // But in such case we have 0 slope(s) lastPoint.slope = lastPoint.slope + userNewPoint.slope - userOldPoint.slope; lastPoint.bias = lastPoint.bias + userNewPoint.bias - userOldPoint.bias; if (lastPoint.slope < 0) { lastPoint.slope = 0; } if (lastPoint.bias < 0) { lastPoint.bias = 0; } } // Record the changed point into history pointHistory[epoch] = lastPoint; if (_addr != address(0)) { // Schedule the slope changes (slope is going down) // We subtract new_user_slope from [new_locked.end] // and add old_user_slope to [old_locked.end] if (_oldLocked.end > block.timestamp) { // oldSlopeDelta was <something> - userOldPoint.slope, so we cancel that oldSlopeDelta = oldSlopeDelta + userOldPoint.slope; if (_newLocked.end == _oldLocked.end) { oldSlopeDelta = oldSlopeDelta - userNewPoint.slope; // It was a new deposit, not extension } slopeChanges[_oldLocked.end] = oldSlopeDelta; } if (_newLocked.end > block.timestamp) { if (_newLocked.end > _oldLocked.end) { newSlopeDelta = newSlopeDelta - userNewPoint.slope; // old slope disappeared at this point slopeChanges[_newLocked.end] = newSlopeDelta; } // else: we recorded it already in oldSlopeDelta } }
#0 - c4-judge
2023-08-22T13:37:29Z
alcueca marked the issue as grade-b