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: 105/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
Issue | Instances | |
---|---|---|
NC-1 | Missing checks for address(0) when assigning values to address state variables | 2 |
NC-2 | Constants in comparisons should appear on the left side | 8 |
NC-3 | delete keyword can be used instead of setting to 0 | 13 |
NC-4 | Lines are too long | 6 |
NC-5 | require() / revert() statements should have descriptive reason strings | 2 |
NC-6 | TODO Left in the code | 2 |
NC-7 | Event is missing indexed fields | 2 |
NC-8 | Functions not used internally could be marked external | 5 |
address(0)
when assigning values to address state variablesInstances (2):
File: GaugeController.sol 59: governance = _governance; // TODO: Maybe change to Oracle
File: LendingLedger.sol 48: governance = _governance; // TODO: Maybe change to Oracle
Constants should appear on the left side of comparisons, to avoid accidental assignment
Instances (8):
File: LendingLedger.sol 37: require(_timestamp % WEEK == 0 || _timestamp == type(uint256).max, "Invalid timestamp"); 64: if (lastUserUpdateEpoch == 0) { 87: if (lastMarketUpdateEpoch == 0) {
File: VotingEscrow.sol 104: if (uepoch == 0) { 142: if (uEpoch == 0) { 274: require(locked_.amount == 0, "Lock exists"); 475: if (epoch == 0) { 492: if (userEpoch == 0) {
It's clearer and reflects the intention of the programmer
Instances (13):
File: GaugeController.sol 78: pt.bias = 0; 79: pt.slope = 0; 104: pt.bias = 0; 105: pt.slope = 0;
File: VotingEscrow.sol 200: lastPoint.bias = 0; 204: lastPoint.slope = 0; 229: lastPoint.slope = 0; 232: lastPoint.bias = 0; 335: newLocked.amount = 0; 336: newLocked.end = 0; 340: newLocked.delegated = 0; 481: lastPoint.bias = 0; 559: lastPoint.bias = 0;
Recommended by solidity docs to keep lines to 120 characters or lesser
Instances (6):
File: LendingLedger.sol 17: mapping(address => mapping(address => mapping(uint256 => uint256))) public lendingMarketBalances; // cNote balances of users within the lending markets, indexed by epoch 21: mapping(address => mapping(uint256 => uint256)) public lendingMarketTotalBalance; // Total balance locked within the market, i.e. sum of lendingMarketBalances for all 26: mapping(address => mapping(address => uint256)) public userClaimedEpoch; // Until which epoch a user has claimed for a particular market (exclusive this value) 136: require(updatedLenderBalance >= 0, "Lender balance underflow"); // Sanity check performed here, but the market should ensure that this never happens 141: require(updatedMarketBalance >= 0, "Market balance underflow"); // Sanity check performed here, but the market should ensure that this never happens 174: cantoToSend += (marketWeight * userBalance * ri.amount) / (1e18 * marketBalance); // (marketWeight / 1e18) * (userBalance / marketBalance) * ri.amount;
require()
/ revert()
statements should have descriptive reason stringsInstances (2):
File: GaugeController.sol 51: require(msg.sender == governance);
File: LendingLedger.sol 42: require(msg.sender == governance);
TODOs may signal that a feature is missing or not ready for audit, consider resolving the issue and removing the TODO comment
Instances (2):
File: GaugeController.sol 59: governance = _governance; // TODO: Maybe change to Oracle
File: LendingLedger.sol 48: governance = _governance; // TODO: Maybe change to Oracle
indexed
fieldsIndex event fields make the field more quickly accessible to off-chain tools that parse events. However, note that each index field costs extra gas during emission, so it's not necessarily best to index the maximum allowed per event (three fields). Each event should use three indexed fields if there are three or more fields, and gas usage is not particularly of concern for the events in question. If there are fewer than three fields, all of the fields should be indexed.
Instances (2):
File: VotingEscrow.sol 21: event Deposit(address indexed provider, uint256 value, uint256 locktime, LockAction indexed action, uint256 ts); 22: event Withdraw(address indexed provider, uint256 value, LockAction indexed action, uint256 ts);
Instances (5):
File: GaugeController.sol 204: function change_gauge_weight(address _gauge, uint256 _weight) public onlyGovernance {
File: VotingEscrow.sol 473: function balanceOf(address _owner) public view returns (uint256) { 487: function balanceOfAt(address _owner, uint256 _blockNumber) public view returns (uint256) { 565: function totalSupply() public view returns (uint256) { 572: function totalSupplyAt(uint256 _blockNumber) public view returns (uint256) {
Unnecessary loss of precision caused by divide before multiplication
Instances (10):
File: GaugeController.sol 60: uint256 last_epoch = (block.timestamp / WEEK) * WEEK; 153: uint256 t = (_time / WEEK) * WEEK; 191: uint256 next_time = ((block.timestamp + WEEK) / WEEK) * WEEK; 224: uint256 next_time = ((block.timestamp + WEEK) / WEEK) * WEEK;
File: LendingLedger.sol 60: uint256 currEpoch = (block.timestamp / WEEK) * WEEK; 84: uint256 currEpoch = (block.timestamp / WEEK) * WEEK; 134: uint256 currEpoch = (block.timestamp / WEEK) * WEEK; 162: uint256 currEpoch = (block.timestamp / WEEK) * WEEK; 174: cantoToSend += (marketWeight * userBalance * ri.amount) / (1e18 * marketBalance); // (marketWeight / 1e18) * (userBalance / marketBalance) * ri.amount;
File: VotingEscrow.sol 425: return (_t / WEEK) * WEEK;
Instances (1):
File: LendingLedger.sol 209: receive() external payable {}
#0 - c4-judge
2023-08-22T14:22:19Z
alcueca marked the issue as grade-b